如何设置依赖项属性值

本文关键字:依赖 属性 设置 何设置 | 更新日期: 2023-09-27 18:09:55

请参考下面的代码。

  • 在启动时,两个文本框的文本将显示"This is the Original Value"。
  • 点击TestBox按钮("测试按钮")时:
    • TestBoxTextBox的文字将变为"Set By Test Button"
    • 另一个文本框的值不会改变。
  • 当点击Window的按钮时,两个文本框的文本应该变为"Set By Window"。但是,只有纯文本框得到更新,TestBox没有。<——这就是BUG!>

似乎我(重新)从TestBox中设置Test属性的方式消除了绑定。

从用户控件本身改变依赖属性而不破坏绑定的正确方法是什么?


示例代码:

我有一个UserControl, TestBox,看起来像这样:

TestBox.xaml:

<UserControl x:Class="Company.UserControls.TestBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Name="TextBoxControl">
    <StackPanel>
        <TextBox MinWidth="100" Name="TestTextBox" 
            Text="{Binding Path=Test, ElementName=TextBoxControl, Mode=TwoWay}" 
         />
        <Button MinWidth="100" Content="Test Button" 
            Click="ButtonBase_OnClick" />
    </StackPanel>
</UserControl>

TestBox.xaml.cs:

using System.Windows;
namespace Company.UserControls
{
    public partial class TestBox
    {
        public const string TestString = "Set By Test Button";
        public TestBox()
        {
            InitializeComponent();
        }
        public static readonly DependencyProperty TestProperty = 
                DependencyProperty.Register(
                    "Test", 
                    typeof(string), typeof(TestBox),
            new FrameworkPropertyMetadata(null, 
                        FrameworkPropertyMetadataOptions.AffectsRender));
        public string Test
        {
            get { return (string)GetValue(TestProperty); }
            set { SetValue(TestProperty, value); }
        }
        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            /****** THIS OBLITERATES THE BINDING ******/
        Test = TestString;
            /****** THIS OBLITERATES THE BINDING ******/
        }
    }
}

和一个像这样使用控件的窗口:

MainWindow.xaml:

<Window x:Class="Company.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:u="clr-namespace:Company.UserControls"
        Title="MainWindow">
    <StackPanel x:Name="MyStackPanel">
        <TextBox Text="{Binding Path=MyTestValue, Mode=OneWay}"/>
        <u:TestBox x:Name="MyTestBox" 
                   Test="{Binding Path=MyTestValue, Mode=OneWay}"/>
        <Button Content="Click" Click="ButtonBase_OnClick" />
    </StackPanel>
</Window>

MainWindow.xaml.cs:

using System.Windows;
namespace Company
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            MyStackPanel.DataContext = new MyThing
            {
                MyTestValue = "This is the Original Value"
            };
        }
        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            MyStackPanel.DataContext = new MyThing
            {
                MyTestValue = "Set by Window"
            };
        }
    }
    public class MyThing
    {
        public string MyTestValue { get; set; }
    }
}

如何设置依赖项属性值

问题是您要求绑定系统不同步。整个系统旨在保持所有绑定元素的同步。只有当绑定模式被设置为"two - way"或"OneWayToSource"时,你才能在不破坏底层绑定的情况下设置依赖属性的值。在这些条件下,值被传送回源,因此,系统保持同步。但是,在您的示例中,双向绑定将导致两个按钮同时更改两个文本框。

您将需要使用两个依赖属性TestBox。第一个依赖属性将被绑定到内部文本框,第二个依赖属性将被绑定到父窗口。然后,您将需要向第二个依赖项属性添加属性更改处理程序(在FrameworkPropertyMetadata中完成)。在这个处理程序中,只需在第一个依赖项属性上设置值。

既然你使用的是带有代码的UserControl,一个更简单的解决方案是只使用上面提到的第二个依赖属性,并直接将值(从你的事件处理程序和属性更改处理程序)通过它的x:Name设置到文本框上。

如果你需要更多的说明,请告诉我。