【问题标题】:How to implement two-way binding on a property?如何在属性上实现双向绑定?
【发布时间】:2016-10-24 14:45:31
【问题描述】:

我知道有很多关于依赖属性的问题,我也看过很多,但似乎没有一个能解决我的问题。

我有一个这样的窗口:

<Window x:Class="WpfBindingTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfBindingTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <StackPanel>
        <local:TextInputWrapper MyText="{Binding MyTextValue, Mode=TwoWay}" />
        <TextBox Text="{Binding MyTextValue, Mode=TwoWay}"/>
    </StackPanel>
</Window>

其中 MyTextValue 只是一个在更改时通知的字符串属性:

    private string _myTextValue = "Totally different value";
    public string MyTextValue { get { return _myTextValue; } set { _myTextValue = value; OnPropertyChanged(); } }
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

TextInputWrapper 也比较简单:

<UserControl x:Class="WpfBindingTest.TextInputWrapper"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfBindingTest"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <TextBox Text="{Binding MyText}"></TextBox>
</UserControl>

代码隐藏:

public partial class TextInputWrapper : UserControl
{
    public static readonly DependencyProperty MyTextProperty = DependencyProperty.Register("MyText",
        typeof(string), typeof(TextInputWrapper), new PropertyMetadata("Empty"));
    public TextInputWrapper()
    {
        InitializeComponent();
    }
    public string MyText
    {
        get { return (string)GetValue(MyTextProperty); }
        set { SetValue(MyTextProperty, value); }
    }

}

现在据我了解,我的 Window 现在应该有 2 个彼此绑定的 TextBox 控件。就像我改变一个值一样,另一个应该更新。

但是,我最终得到了 2 个单独的文本框,其中第一个以文本“空”开头,下一个以文本“完全不同的值”开头。像这样:

并且更改其中任何一个的文本都不会在另一个中重现。

我希望它们都从文本“完全不同的值”开始,并与它们的值同步(通过传播对 MainWindow 上的 MyTextValue 属性的更改,并通知那里的更改,然后更改会向上传播到另一个文本框)。在我的控件中正确实现数据绑定缺少什么?

【问题讨论】:

  • 在UserControl中,{Binding MyText, RelativeSource={RelativeSource AncestoyType=UserControl}},并且不要将UserControl的DataContext绑定到Self。正如你所拥有的,它不能绑定到视图模型。

标签: c# .net wpf data-binding wpf-controls


【解决方案1】:

删除分配

DataContext="{Binding RelativeSource={RelativeSource Self}}"

来自 UserControl 的 XAML。相反,将“内部”绑定的RelativeSource 设置为控件实例:

<UserControl x:Class="WpfBindingTest.TextInputWrapper" ...>
    <TextBox Text="{Binding MyText,
                    RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</UserControl>

显式设置 UserControl 的 DataContext 可防止从其父控件继承 DataContext,即类似 Binding

<local:TextInputWrapper MyText="{Binding MyTextValue, Mode=TwoWay}" />

将使用 UserControl 作为源对象,而不是当前的 DataContext。


作为一般规则,从不显式设置 UserControl 的 DataContext。

【讨论】:

  • 这似乎确实奏效了。谢谢!有什么地方可以读到这个吗?特别是RelativeSource 部分。
  • MSDN 上的Data Binding Overview 文章应该会给你一个好的开始。
【解决方案2】:

尝试更改此行:

public static readonly DependencyProperty MyTextProperty = DependencyProperty.Register("MyText",
typeof(string), typeof(TextInputWrapper), new PropertyMetadata("Empty"));

到这里:

public static readonly DependencyProperty MyTextProperty = DependencyProperty.Register("MyText",
    typeof(string), typeof(TextInputWrapper), new FrameworkPropertyMetadata("Empty", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

【讨论】:

  • 你看到MyText="{Binding MyTextValue, Mode=TwoWay}"了吗?
  • 不,我实际上没有。尽管如此,无论如何覆盖默认绑定行为可能还是有用的(尽管这不是问题)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 2013-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多