C# 代码中定义的 WPF 数据绑定问题不更新 UI 元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/406526/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 02:10:41  来源:igfitidea点击:

Problem with WPF Data Binding Defined in Code Not Updating UI Elements

c#wpfdata-bindinginotifypropertychanged

提问by Ben McIntosh

I need to define new UI Elements as well as data binding in code because they will be implemented after run-time. Here is a simplified version of what I am trying to do.

我需要在代码中定义新的 UI 元素以及数据绑定,因为它们将在运行时之后实现。这是我正在尝试做的事情的简化版本。

Data Model:

数据模型:

public class AddressBook : INotifyPropertyChanged
{
    private int _houseNumber;
    public int HouseNumber
    {
        get { return _houseNumber; }
        set { _houseNumber = value; NotifyPropertyChanged("HouseNumber"); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string sProp)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(sProp));
        }
    }
}

Binding in Code:

代码绑定:

AddressBook book = new AddressBook();
book.HouseNumber = 123;
TextBlock tb = new TextBlock();
Binding bind = new Binding("HouseNumber");
bind.Source = book;
bind.Mode = BindingMode.OneWay;
tb.SetBinding(TextBlock.TextProperty, bind); // Text block displays "123"
myGrid.Children.Add(tb);
book.HouseNumber = 456; // Text block displays "123" but PropertyChanged event fires

When the data is first bound, the text block is updated with the correct house number. Then, if I change the house number in code later, the book's PropertyChanged event fires, but the text block is not updated. Can anyone tell me why?

当第一次绑定数据时,文本块会更新为正确的门牌号。然后,如果我稍后在代码中更改门牌号,则会触发该书的 PropertyChanged 事件,但不会更新文本块。谁能告诉我为什么?

Thanks, Ben

谢谢,本

采纳答案by Ben McIntosh

The root of it was that the string I passed to PropertyChangedEventArgs did not EXACTLY match the name of the property. I had something like this:

其根源在于我传递给 PropertyChangedEventArgs 的字符串与属性名称不完全匹配。我有这样的事情:

public int HouseNumber
{
    get { return _houseNumber; }
    set { _houseNumber = value; NotifyPropertyChanged("HouseNum"); }
}

Where it should be this:

它应该在哪里:

public int HouseNumber
{
    get { return _houseNumber; }
    set { _houseNumber = value; NotifyPropertyChanged("HouseNumber"); }
}

Yikes! Thanks for the push in the right direction.

哎呀!感谢您朝着正确的方向努力。

回答by Steven Robbins

Do you need to set the binding mode programatically? It may be defaulting to OneTime.

是否需要以编程方式设置绑定模式?它可能默认为 OneTime。

回答by Giraffe

Are you sure you're updating the same object as you've used in the binding? At first glance nothing looks wrong, so check the simple things. :)

您确定要更新与绑定中使用的对象相同的对象吗?乍一看没有什么问题,所以检查简单的事情。:)

回答by Marc Gravell

Does any code bypass the property, setting the field (_houseNumber) directly?

是否有任何代码绕过该属性,_houseNumber直接设置字段 ( )?

回答by Cameron MacFarland

Make sure you're updating the AddressBookreference that was used in the binding, and not some other AddressBookreference.

确保您正在更新AddressBook绑定中使用的引用,而不是其他一些AddressBook引用。

I got the following to work with the AddressBook code you gave.

我得到了以下内容来处理您提供的 AddressBook 代码。

<StackPanel>
    <Button Click="Button_Click">Random</Button>
    <Grid x:Name="myGrid">
    </Grid>
</StackPanel>

Code behind:

后面的代码:

public partial class Window1 : Window
{
    private AddressBook book;

    public Window1()
    {
        InitializeComponent();

        book = new AddressBook();
        book.HouseNumber = 13;

        TextBlock tb = new TextBlock();
        Binding bind = new Binding("HouseNumber");
        bind.Source = book;
        tb.SetBinding(TextBlock.TextProperty, bind);
        myGrid.Children.Add(tb);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Random rnd = new Random();
        book.HouseNumber = rnd.Next();
    }
}

Note the same reference is used in the update code.

请注意,更新代码中使用了相同的引用。

回答by Steven Robbins

I've just cut+pasted your code (and added a little), and it works fine for me:

我刚刚剪切+粘贴了您的代码(并添加了一点),它对我来说很好用:

    public Window1()
    {
        InitializeComponent();

        AddressBook book = new AddressBook();
        book.HouseNumber = 123;
        TextBlock tb = new TextBlock();
        Binding bind = new Binding("HouseNumber");
        bind.Source = book;
        bind.Mode = BindingMode.OneWay;
        tb.SetBinding(TextBlock.TextProperty, bind); // Text block displays "123"
        myGrid.Children.Add(tb);
        book.HouseNumber = 456; 
    }

    private void TestButton_Click(object sender, RoutedEventArgs e)
    {
        AddressBook book = 
           (AddressBook(TextBlock)
              myGrid.Children[0])
              .GetBindingExpression(TextBlock.TextProperty)
              .DataItem;

        book.HouseNumber++;
    }

Displays 456 on startup, clicking the button makes the number in the TextBlock increment just fine.

启动时显示 456,单击按钮使 TextBlock 中的数字增量就好了。

Perhaps you are looking in the wrong place for the cause of the problem?

也许您在错误的地方寻找问题的原因?