WPF中的双向绑定

31

我无法让WPF中的双向绑定正常工作。

我在应用程序的主窗口中有一个字符串属性,它与TextBox绑定(我将模式设置为“TwoWay”)。

仅当窗口初始化时,TextBox的值才会更新。

当我在TextBox中输入时,底层字符串属性的值不会更改。

当字符串属性的值由外部源(例如单击事件,只是重置TextBox的值)更改时,更改不会传播到TextBox。

我必须实现哪些步骤才能使双向绑定在这个几乎微不足道的例子中正常工作?

4个回答

61
很可能你正在尝试绑定到一个 .net CLR 属性,而不是 WPF dependencyProperty(除了其他一些功能之外,它提供变更通知)。对于普通的 CLR 属性,你需要实现 INotifyPropertyChanged 接口,并在 PropertyChanged 的事件处理程序中强制更新文本框。
因此,让拥有属性的对象实现此接口,在属性设置器中引发事件(现在我们有了属性更改通知)。确保该对象设置为 UI 元素/控件的 DataContext 属性。
当我开始学习 WPF 数据绑定时,我也遇到了这个问题。
更新:嗯 OP,如果我走错了路,那会浪费时间... 无论如何,既然你不得不挖掘一下... 那么你会记住它很长时间。这是代码片段,以结束这个答案。还发现,只要我按 Tab 离开,就会自动更新文本框... 如果你的 datacontext 对象不是实现 INotifyPropertyChanged 的对象,则只需要手动订阅事件并更新 UI。

MyWindow.xaml
<Window x:Class="DataBinding.MyWindow" ...
    Title="MyWindow" Height="300" Width="300">
    <StackPanel x:Name="TopLevelContainer">
        <TextBox x:Name="txtValue"  Background="AliceBlue" Text="{Binding Path=MyDotNetProperty}" />
        <TextBlock TextWrapping="Wrap">We're twin blue boxes bound to the same property.</TextBlock>
        <TextBox x:Name="txtValue2"  Background="AliceBlue" Text="{Binding Path=MyDotNetProperty}" />
    </StackPanel>
</Window>

MyWindow.xaml.cs

public partial class MyWindow : Window, INotifyPropertyChanged
{
    public MyWindow()
    {
        InitializeComponent();
        this.MyDotNetProperty = "Go ahead. Change my value.";
        TopLevelContainer.DataContext = this;
    }

    private string m_sValue;
    public string MyDotNetProperty
    {
        get { return m_sValue; }
        set
        {
            m_sValue = value;
            if (null != this.PropertyChanged)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("MyDotNetProperty"));
            }
        }
    }

    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion
}

5
这个对我有帮助,所以点赞 +1,但在我的{xaml}的{Binding}定义中还需要包含 UpdateSourceTrigger=PropertyChanged 才能使它起作用。 - Joel Brown

5
我感觉需要补充一些细节:
“双向”数据绑定不仅仅是“单向”数据绑定。
“单向”数据绑定是从源到依赖属性的绑定。源必须实现INotifyPropertyChanged,以便从源到目标进行更改传播。
要获得“双向”,也就是从目标到源进行传播,这取决于您在绑定上设置的绑定模式。如果您没有为绑定设置任何BindingMode,则将使用默认的Binding mode,并且此默认模式是目标Dependency Property的特性。
例如:一个绑定到名为“MyTextProperty”的字符串属性的文本框。在代码中,您将Textbox.Text DependencyProperty绑定到“MyObject”对象上的“MyTextProperty”。
-> “单向”绑定: “My TextProperty”的setter必须引发事件Property Changed,并且“MyObject”必须实现INotifyPropertyChanged。
-> “双向”数据绑定:除了“单向”所需的内容之外,还必须将bindingMode设置为“2 ways”。在这种特殊情况下,Textbox的Text DependencyProperty确实具有“2 ways”作为默认模式,因此不需要做其他事情!

3
我们可能需要查看代码。你的字符串属性是否引发PropertyChanged事件?或者(更好的选择)它是否实现为DependencyProperty?如果没有,绑定的TextBox将不知道值何时更改。
至于在TextBox中输入而未看到属性值更改,这可能是因为你的TextBox没有失去焦点。默认情况下,绑定的TextBox在焦点离开控件之前不会将其值写回源属性。尝试切换到其他控件并查看属性值是否更改。

2

请确保绑定指定为双向,当属性发生更改时,立即将其传输到持有属性。

 <TextBox Text="{Binding TextBuffer, 
                         UpdateSourceTrigger=PropertyChanged, 
                         Mode=TwoWay}"/>

以上保证了TextBox输入控件的Text属性绑定到字符串属性TextBuffer,并以立即、PropertyChangedTwoWay的方式发送更改。

UpdateSourceTrigger是我在一个不起作用的双向绑定中缺失的东西。 - onezeno
我也缺少了UpdateSourceTrigger...非常感谢! - CodeMylife

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