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
Problem with WPF Data Binding Defined in Code Not Updating UI Elements
提问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 AddressBook
reference that was used in the binding, and not some other AddressBook
reference.
确保您正在更新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?
也许您在错误的地方寻找问题的原因?