WPF 绑定到变量/DependencyProperty

发布于 2024-10-09 14:53:36 字数 1979 浏览 1 评论 0原文

我正在研究 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 绑定,也就是说您可以更改 TextBox 内容,从而更改属性,但显然永远不会调用 Setter。 我想知道为什么会这样,以及如何实现预期的行为。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦巷 2024-10-16 14:53:36

依赖属性的 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
}

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
}
待天淡蓝洁白时 2024-10-16 14:53:36

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

检查下面的链接并通读 Robert Rossney 的帖子,以获得公平的概述

WPF:依赖属性与常规 CLR 属性有何区别?< /a>

也不要错过

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

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

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

http://blogs.msdn.com/b/delay/archive/2010/03/23 /做一件事并做好它提示-clr-wrapper-for-a-dependencyproperty-should-do-its-job-and-nothing-more.aspx

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文