When a property is changed via TwoWay binding, the variable is not operated, only with the dependency property.

Marked in the code comments the right places.

I know the workarounds (the most obvious - through PropertyChanged), but is it really that bad?

The question, in fact, is how easy it is to make two-way binding?

The project is here: https://yadi.sk/d/ioEe0PZ2v7pEC

MainWindow.xaml

<Window x:Class="SampleProject.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Sample" Height="100" Width="500"> <UniformGrid Columns="1" Margin="5"> <!-- Привязка на следующей строке НЕ вызовет setter переменной SliderValue --> <Slider Value="{Binding SliderValue, RelativeSource={RelativeSource AncestorType=Window}}"/> <TextBlock Text="{Binding TextValue, RelativeSource={RelativeSource AncestorType=Window}}"/> </UniformGrid> </Window> 

MainWindow.xaml.cs

 using System.Windows; namespace SampleProject { public partial class MainWindow { public MainWindow() { InitializeComponent(); SliderValue = 3.123456789; // <<== Это вызовет setter переменной SliderValue } // ==>> TextBlock.Text public string TextValue { get { return (string)GetValue(_propTextValue); } set { SetValue(_propTextValue, value); } } public static readonly DependencyProperty _propTextValue = DependencyProperty.Register("TextValue", typeof(string), typeof(MainWindow), new FrameworkPropertyMetadata("Ожидание значения...")); // ==>> Slider.Value public double SliderValue { get { return (double) GetValue(_propSliderValue); } set { TextValue = value.ToString(); SetValue(_propSliderValue, value); } } public static readonly DependencyProperty _propSliderValue = DependencyProperty.Register("SliderValue", typeof(double), typeof(MainWindow), new FrameworkPropertyMetadata(5.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); } } 

    1 answer 1

    You violated the DependencyProperty contract: your static fields should be named TextValueProperty and SliderValueProperty respectively (and not _propTextValue and _propSliderValue ).

    Rename.

    In addition, for some reason you hope that your setter will be invoked by a WPF framework. No, this is also not guaranteed. You need to associate dependency property through property change callback:

     public double SliderValue { get { return (double) GetValue(SliderValueProperty); } set { SetValue(SliderValueProperty, value); } } public static readonly DependencyProperty SliderValueProperty = DependencyProperty.Register( "SliderValue", typeof(double), typeof(MainWindow), new FrameworkPropertyMetadata( 5.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSliderChange)); static void OnSliderChange(DependencyObject o, DependencyPropertyChangedEventArgs args) { var self = (MainWindow)o; self.TextValue = args.NewValue.ToString(); } 

    Or a little easier:

     public double SliderValue { get { return (double) GetValue(SliderValueProperty); } set { SetValue(SliderValueProperty, value); } } public static readonly DependencyProperty SliderValueProperty = DependencyProperty.Register( "SliderValue", typeof(double), typeof(MainWindow), new FrameworkPropertyMetadata( 5.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (o, args) => o.SetValue(TextValueProperty, args.NewValue.ToString())); 
    • Thanks for the naming information — MSDN strongly recommends. But the question did not dare. And, of course, I understand the ways around it. But when the interface is complex, and the interrelation of variables is not always clear in advance, the approach you recommend is ineffective. - ZloyMakak
    • @ZloyMakak: Please! Unsubscribe from the results. - VladD
    • @ZloyMakak: Uh, the approach may be ineffective, but you have nothing else. Calling the setter is not guaranteed (and will most often be ignored). Well, I do not see the problem of efficiency: if you have complex calculations, you should still do them in the model, not in the UI. - VladD
    • Yes, I know about the workaround. But how can I not want to recognize the correct decision of this mechanism. But I’ve already rummaged the entire Internet - people somehow live with it ... - ZloyMakak
    • “No, this is also not guaranteed” - but isn't the opposite guaranteed? As far as I remember, if the source of the changes is XAML, then SetValue always called directly - ixSci