Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Binding to variable / DependencyProperty

I'm playing around with WPF Binding and variables. Apparently one can only bind DependencyProperties. I have come up with the following, which works perfectly fine: The code-behind file:

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

    public string Test
    {
        get { return (string)this.GetValue(TestProperty); }
        set { this.SetValue(TestProperty, value); }
        //set { this.SetValue(TestProperty, "BBB"); }
    }
    public static readonly DependencyProperty TestProperty = DependencyProperty.Register(
      "Test", typeof(string), typeof(MainWindow), new PropertyMetadata("CCC"));

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(Test);
        Test = "AAA";
        MessageBox.Show(Test);
    }
}

XAML:

<Window x:Class="WpfApplication3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    Title="MainWindow" Height="350" Width="525"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
    <TextBox Height="31" HorizontalAlignment="Left" Margin="84,86,0,0" Name="textBox1" VerticalAlignment="Top" Width="152" 
             Text="{Binding Test, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}"/>
    <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="320,85,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    <TextBox Height="31" HorizontalAlignment="Left" Margin="84,138,0,0" Name="textBox2" Text="{Binding Test, Mode=TwoWay}" VerticalAlignment="Top" Width="152" />
</Grid>

The two TextBoxes update one an other. And the Button sets them to "AAA".

But now I replaced the Setter function with the one that is commented out (simulating some manipulation of the given value). I would expect that whenever the property value is changed it will be reset to "BBB". It does so when you press the button, that is when you set the property in code. But it does for some reason not affect the WPF Bindings, that is you can change the TextBox contents and thus the property, but apparently the Setter is never called. I wonder why that is so, and how one would go about to achive the expected behaviour.

like image 506
PeterE Avatar asked Dec 28 '10 16:12

PeterE


2 Answers

The CLR Property wrapper for a Dependency Property is never guaranteed to be called and therefore, you should never place any additional logic there. Whenever you need additional logic when a DP is changed, you should use the property changed callback.

In your case..

public string Test
{
    get { return (string)this.GetValue(TestProperty); }
    set { this.SetValue(TestProperty, value); }
}

public static readonly DependencyProperty TestProperty =
    DependencyProperty.Register("Test",
    typeof(string),
    typeof(MainWindow),
    new PropertyMetadata("CCC", TestPropertyChanged));

private static void TestPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
    MainWindow mainWindow = source as MainWindow;
    string newValue = e.NewValue as string;
    // Do additional logic
}
like image 76
Fredrik Hedblad Avatar answered Sep 29 '22 01:09

Fredrik Hedblad


Your change will not affect the binding because the XAML will call SetValue directly, instead of calling your property setter.That is how the dependency property system works.When a dependency property is registered a default value can be specified.This value is returned from GetValue and is the default value for your property.

Check the link below and read through to Robert Rossney's post to get a fair overview

WPF: What distinguishes a Dependency Property from a regular CLR Property?

also don't miss

http://msdn.microsoft.com/en-us/library/ms753358.aspx

and

http://msdn.microsoft.com/en-us/library/ms752914.aspx

Also note that unlike in normal CLR properties any custom logic you write in the setter will not be executed in Dependency Properties,instead you have to use the PropertyChangedCallback mechanism

http://blogs.msdn.com/b/delay/archive/2010/03/23/do-one-thing-and-do-it-well-tip-the-clr-wrapper-for-a-dependencyproperty-should-do-its-job-and-nothing-more.aspx

like image 28
biju Avatar answered Sep 29 '22 03:09

biju