WPF绑定只对基本视图模型属性第一次起作用



我们有一个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

最新更新