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

问题描述:

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

数据模型:

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)); 
     } 
    } 
} 

在代码绑定:

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 

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

感谢, 本

+0

您是否尝试设置断点以查看它们在设置属性时是否被击中? – John 2009-01-02 11:24:48

+0

是的,当本书的PropertyChanged事件触发时,我会弹出一个消息框,这会在每次数据更新时发生。 – 2009-01-02 11:32:55

+0

[最有趣的答案](http:// *。com/a/406595/200449),国际海事组织,由@StevenRobbins,虽然是undervoted,然后埋在其他答案 – 2013-04-19 08:04:32

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

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

,它应该是这样的:

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

哎呀!感谢您的正确方向。

你需要编程设置结合模式?它可能默认为OneTime。

+0

感谢您的建议,但增加: bind.Mode = BindingMode.OneWay; 没有效果。 – 2009-01-02 11:28:24

+0

我可能会误读,但听起来像Beepcake意味着尝试将BindingMode设置为BindingMode.TwoWay。 TextBlocks默认是单向的。 – Jab 2009-01-02 17:54:26

+0

有问题的代码真的没有设置任何`BindingMode`工作 – 2013-04-19 08:00:25

您确定您正在更新绑定中使用的相同对象吗?乍一看没有错,请检查简单的事情。 :)

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

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

我得到以下与您提供的AddressBook代码一起使用。

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

后面的代码:

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(); 
    } 
} 

注相同的参考在更新代码中使用。

我只是削减+粘贴您的代码(加了一点),它为我工作得很好:

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++; 
    } 

显示456在启动时,单击按钮使得在TextBlock的增量数只精细。

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