WPF绑定只对基本视图模型属性第一次起作用
本文关键字:模型 属性 第一次 起作用 视图 绑定 WPF | 更新日期: 2023-09-27 17:53:27
我们有一个Item Details窗口,它使用ViewModel的实例作为DataContext。我们在ViewModel上有一个简单的字符串属性,叫做StatusMessage,用来给用户反馈。我们已经在这个视图模型上实现了INotifyPropertyChanged,并且配置了StatusMessage属性来引发事件。ViewModel还有另外三个成员,它们是类(或集合),在所有这些成员上,绑定都像它们应该的那样工作。
问题是当StatusMessage在GUI中被编程更改时,它不会得到更新。我们已经调试并发现属性确实在改变,我们订阅了属性改变事件后的窗口代码,可以看到事件确实在触发。
任何绑定到StatusMessage的控件都将显示构造函数中设置的内容,但之后不会更新。
我使用了两个不同的控件,一个是双向绑定的文本框,另一个是标签,都绑定到StatusMessage。当我使用TextBox更改值时,我的标签也会更改。但是ViewModel内部所做的任何更改都不会传播到GUI。
没有绑定错误。我们甚至检查了PropertyChanged事件处理程序上的HasBindingErrors属性,它显示为false,并显示我们的控件仍然绑定到StatusMessage。
这个问题只影响基/根ViewModel类。所有的成员都是类,有自己的成员,并实现INotifyPropertyChanged工作没有任何问题。我们有完整的双向绑定,它们都可以工作。
我试过清理和重建项目,但没有任何区别。
什么可能导致绑定失败而不产生任何错误消息?
这是实际的代码,虽然我不得不修剪了很多为了使它适合这里:
XAML:<Window x:Class="PZESpecsApp.SpecDetails"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:local="clr-namespace:SpecsApp"
Title="Spec Details" Height="600" Width="1000">
<Grid>
<TextBlock Text="{Binding spec.MakeAndModelNo}" FontSize="24" FontWeight="Bold" Margin="16,10,0,0" />
<TextBox Name="txtStatusMessage" Text="{Binding StatusMessage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="24" FontWeight="Bold" Foreground="Black" />
<Label Grid.Column="0" Content="{Binding Path=StatusMessage}" Foreground="White" />
</Grid>
</Window>
窗口代码:
public partial class SpecDetails : Window
{
private SpecDetailsViewModel model;
public SpecDetails(int id)
{
InitializeComponent();
model = new SpecDetailsViewModel(id);
model.PropertyChanged += ViewModel_PropertyChanged;
DataContext = model;
}
private void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
//this shows that the property actually changes as expected
Debug.Print("PropertyChanged=" + e.PropertyName);
}
}
ViewModel Code:
public class SpecDetailsViewModel
{
public event PropertyChangedEventHandler PropertyChanged;
private Spec _spec;
public Spec spec
{
get { return _spec; }
set { _spec = value; PropertyChanged.Notify(() => this.spec); }
}
private string _statusMessage;
public string StatusMessage
{
get { return _statusMessage; }
set { _statusMessage = value; PropertyChanged.Notify(() => this.StatusMessage); }
}
public SpecDetailsViewModel(int id)
{
spec = AppData.SpecsList.FirstOrDefault(s => s.id == id);
StatusMessage = "Monkey See, Monkey Do!"; //this stays on the GUI
}
public void SaveSpec() {
//this doesn't have any affect on the GUI
this.StatusMessage = "Changes Saved";
}
}
好了,我找到问题了。我猜你可以说我们隐式地实现了INotifyPropertyChanged,显然那还不够好。修复是在ViewModel类中:
public class SpecDetailsViewModel : INotifyPropertyChanged