Home > Back-end >  `IsChecked` Binding Fails for no Apparent Reason
`IsChecked` Binding Fails for no Apparent Reason

Time:11-10

I’m trying to learn XAML (without much success) – be gentle.

I have a toggle button, a slider and a button. This is what I am trying to do:

  1. When the slider’s value is changed the toggle button should turn off – works fine.
  2. When the button is pressed, set the slider value and keep the toggle button in whichever state it is – does not work; after I push the button, (1) does not work anymore. It behaves like the IsChecked binding was cleared.

Ideally I would like to write everything in XAML, but I guess it is not possible.

// MainWindow.xaml.cs
public class ValueToFalse : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return false;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var saved = toggle.IsChecked;
        slider.Value = 2;
        toggle.IsChecked = saved;
    }

}
<!--App.xaml-->
<local:ValueToFalse x:Key="ValueToFalse"/>
<!--MainWindow.xaml-->
  <ToggleButton 
      Name="toggle"
      Content="toggle" 
      HorizontalAlignment="Left" 
      Margin="479,64,0,0" 
      VerticalAlignment="Top" 
      Height="108" 
      Width="192"
      IsChecked="{Binding Value, Mode=OneWay, ElementName=slider, Converter={StaticResource ValueToFalse} }"
      />

    <Slider 
        Name="slider"
        HorizontalAlignment="Left" 
        Margin="167,105,0,0" 
        VerticalAlignment="Top" 
        Width="233"
        Height="35"
        />
    
    <Button 
        Content="Button" 
        HorizontalAlignment="Left" 
        Margin="346,340,0,0" 
        VerticalAlignment="Top" 
        Click="Button_Click"
        />

CodePudding user response:

I didn't quite understand what you want to implement. But nevertheless, you have an obvious mistake that @Clemens pointed out - if you need to assign a Dependency Property value and keep the binding from it, then the binding must be in the direction of the TwoWay or OneWaySource source.

Since you do not need to assign a value to the source, but you need to store the direction to the source in the binding, you can solve this by implementing a converter.

I show the full implementation of the converter with markup extension. This may be useful to you in the future.

    [ValueConversion(typeof(object), typeof(bool))]
    public class ValueToFalseConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return false;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // This value tells the binding that the result of the conversion should not be assigned.
            return Binding.DoNothing;
        }

        private ValueToFalseConverter() { }
        public static ValueToFalseConverter Instance { get; } = new ValueToFalseConverter();
    }

    [MarkupExtensionReturnType(typeof(ValueToFalseConverter))]
    public class ValueToFalseExtension : MarkupExtension
    {
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return ValueToFalseConverter.Instance ;
        }
    }
  <ToggleButton 
      ----------
      ----------
      IsChecked="{Binding Value,
                          Mode=TwoWay, 
                          ElementName=slider, 
                          Converter={local:ValueToFalse}}"
      />
  • Related