WPF绑定仅适用于基本视图模型属性的第一次

时间:2015-06-03 22:07:13

标签: c# wpf xaml mvvm

我们有一个Item Details窗口,它使用ViewModel的一个实例作为DataContext。我们在ViewModel上有一个名为StatusMessage的简单字符串属性,用于向用户提供反馈。我们在此视图模型上实现了INotifyPropertyChanged,并且StatusMessage属性配置为引发事件。 ViewModel有三个其他成员,它们是类(或集合),在所有这些工作中,绑定的工作方式应该如此。

问题是,当以编程方式更改时,StatusMessage不会在GUI中更新。我们已经调试并发现该属性确实在发生变化,而我们订阅了属性更改事件后面的Window代码,并且可以看到该事件确实正在触发。

绑定到StatusMessage的任何控件都将显示构造函数上设置的内容,但在此之后它永远不会更新。

我使用了两个不同的控件,一个是带有twoway绑定的文本框,另一个是标签,两者都绑定到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代码:

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

1 个答案:

答案 0 :(得分:2)

好的,我发现了问题。我猜你可以说我们隐含地实现了INotifyPropertyChanged,显然这还不够好。修复程序位于ViewModel类中:

public class SpecDetailsViewModel : INotifyPropertyChanged