WPF绑定不更新视图

时间:2014-08-27 08:20:43

标签: c# wpf xaml mvvm

我有一个文本块:

<TextBlock HorizontalAlignment="Left" Name="StatusText" Margin="0,20" TextWrapping="Wrap" Text="{Binding StatusText}">
            ... Status ...
</TextBlock>

代码隐藏:

public StatusPage()
{
    InitializeComponent();
    this.DataContext = new StatusPageViewModel(this);
}

并在viewModel中:

private string _statusText;
/// <summary>
/// Status text
/// </summary>
public string StatusText
{
    get { return _statusText; }
    set { _statusText = value; }
}

和viewModel中的函数:

string statusText = Status.GetStatusText();
this.StatusText = statusText;

GetStatusText()返回类似“完成工作”的字符串等。来自该函数的值被赋予this.StatusText,但TextBlock的文本属性不会更改,并且仍显示占位符“...状态。 ..“

我知道这样的问题 - &gt; CLICK&lt; ---但在阅读完之后我仍然无法找到解决方案

@Update

根据你的建议我更新了我的代码,现在我有了这个:

public string StatusText
{
    get 
    {
        return _statusText;
    }
    set 
    {
        _statusText = value; 
        RaisePropertyChanged("StatusText");
    }
}

和viewModel的声明:

 public class StatusPageViewModel : ObservableObject, INavigable

其中:

ObservableObject类是:

public abstract class ObservableObject : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

    /// <summary>
    /// Raises the PropertyChange event for the property specified
    /// </summary>
    /// <param name="propertyName">Property name to update. Is case-sensitive.</param>
    public virtual void RaisePropertyChanged(string propertyName)
    {
        OnPropertyChanged(propertyName);
    }

    /// <summary>
    /// Raised when a property on this object has a new value.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Raises this object's PropertyChanged event.
    /// </summary>
    /// <param name="propertyName">The property that has a new value.</param>
    protected virtual void OnPropertyChanged(string propertyName)
    {

        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }

    #endregion // INotifyPropertyChanged Members
}

但它仍无效

6 个答案:

答案 0 :(得分:22)

您需要在ViewModel顺序中实现INotifyPropertyChanged,以通知View该属性已更改。

以下是指向MSDN页面的链接:System.ComponentModel.INotifyPropertyChanged

最重要的是要注意在属性设置器中引发PropertyChanged事件。

答案 1 :(得分:10)

双向添加绑定模式,因为默认情况下Textblock的绑定模式是单向

<TextBlock HorizontalAlignment="Left" Name="StatusText" Margin="0,20" TextWrapping="Wrap" Text="{Binding StatusText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            ... Status ...
</TextBlock>

当然,您需要为此目的实施 INotifyPropertyChanged ,请参阅this link了解如何实施。

答案 2 :(得分:3)

使用DataModels时,您必须确保模型在初始加载时完成。因此,如果你这样做:this.DataContext = mainViewModel和你的mainViewModel的某些部分没有加载(= null),那么你无法绑定它们。例如,我在该模型中有一个Model对象程序。我将TextBlock的Text绑定到Model.Program.Name。 Program对象在初始加载时未连接,因此您必须重新绑定到加载的对象,否则无法发送通知。

答案 3 :(得分:2)

您的视图模型需要实现INotifyPropertyChanged,并且每次您的某个属性更改时(即在setter中)都需要提升它。

没有它,WPF无法知道该属性已经发生变化。

答案 4 :(得分:0)

我遇到了这个问题,这就是我做错了......

注意:我已正确编码INotifyPropertyChanged。

在我看来,我有

<SomeView.DataContext>
    <SomeViewModel/>
<SomeView.DataContext/>

...这会调用VM的构造函数(创建指向/要绑定的实例)。

在另一个类中(在我的程序的主窗口的ViewModel代码中)我也在实例化ViewModel,即:

private SomeAstractBaseViewModel someViewModel = new SomeViewModel();
private SomeAstractBaseViewModel someOtherViewModel = new SomeOtherViewModel(); 

它们都是从超类继承的,我在主窗口的一个部分中显示不同视图的实例之间来回切换 - 按照我的意图。

如何连接所有内容是另一个问题,但是当我删除之前实例化另一个&#34的有问题的 xaml (在此答案的顶部)未使用&#34; ViewModel的实例,View将根据 INotifyPropertyChanged 机制进行更新。

答案 5 :(得分:0)

在我的情况下,一个UserControl嵌套在一个View中,当我尝试BindingUserControl内的某个属性时,框架在ViewModel(不存在)。为了解决这个问题,我必须指定ElementName

MyControl.xaml:

<UserControl
    ...
    x:Name="MyUserControl">
    ...
    <Label Content="{Binding MyProperty, ElementName=MyUserControl}"
    ...

MyControl.xaml.cs:

public partial class MyControl: UserControl, INotifyPropertyChanged
{
    ...
    private string _myProperty = "";

    public string MyProperty
    {
        get => _myProperty ;
        set
        {
            if (value == _myProperty ) return;
            _myProperty = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    ...