WPF绑定到变量/依赖属性

6

我正在研究WPF绑定和变量。显然,只有DependencyProperties才能进行绑定。我想出了以下代码,它完全正常:

代码后台文件:

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>

这两个文本框会相互更新。而按钮会将它们设置为“AAA”。

但现在我用注释掉的Setter函数替换了它(模拟对给定值的某些操作)。我期望每当属性值被更改时,它都会被重置为“BBB”。当您按下按钮时,也就是在代码中设置属性时,它确实如此。但由于某种原因,它不会影响WPF绑定,也就是说您可以更改文本框内容和属性,但显然Setter从未被调用。 我想知道为什么会这样,并且如何才能实现预期的行为。


可能是WPF:通过Setters未设置XAML属性声明?的重复问题。 - Tim Pohlmann
2个回答

14

CLR属性包装器对于依赖属性来说从不保证被调用,因此,您不应该在那里放置任何额外的逻辑。每当需要在更改 DP 时进行额外的逻辑处理时,应使用属性更改回调。

在您的情况下...

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
}

3

因为XAML会直接调用SetValue而不是调用属性设置器,所以您的更改不会影响绑定。这就是依赖属性系统的工作原理。当注册依赖属性时,可以指定默认值。该值从GetValue返回,并且是属性的默认值。

请查看下面的链接并阅读Robert Rossney的帖子,以获得公正的概述

WPF:什么区别依赖属性和常规CLR属性?

也不要错过

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

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

请注意,与普通CLR属性不同,您在设置器中编写的任何自定义逻辑都不会在依赖属性中执行,而是必须使用PropertyChangedCallback机制。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接