【问题标题】:WPF binding not updating the viewWPF 绑定不更新视图
【发布时间】:2014-10-20 17:55:20
【问题描述】:

我有一个文本块:

<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 的文本属性没有改变,并且仍然显示占位符“...状态...”

我知道这样的问题 --> CLICK

@更新

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

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
}

但是还是不行

【问题讨论】:

  • 你的问题解决了吗?
  • 那么解决方案是什么?我面临同样的问题。实现了INotifyPropertyChanged,Mode 1way/2ways没有区别。
  • 我也有同样的问题。在应用程序运行时更改绑定属性后(例如 OneWay/TwoWay),属性的 getter 被调用,一切看起来都很好,但重新启动后它仍然无法正常工作。
  • 它可能会在将来对某人有所帮助,但是尽管实现了接口,但我忘记在我的 MainWindow 类声明中实际引用它。例如:MainWindow : Window, INotifyPropertyChanged

标签: c# wpf xaml mvvm


【解决方案1】:

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

这是 MSDN 页面的链接:System.ComponentModel.INotifyPropertyChanged

需要注意的最重要的一点是,您应该在属性设置器中引发 PropertyChanged 事件。

【讨论】:

  • 尝试将您的 Binding.Mode 属性设置为 OneWay - 可能是 UI 没有监听更新。
【解决方案2】:

添加两种绑定方式,因为默认Textblock的绑定方式是一种方式

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

当然你也需要实现INotifyPropertyChanged,具体实现方法请参考this link

【讨论】:

  • 双向绑定毫无意义,因为控件无法更改文本,因此无需更新源代码。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    没有它,WPF 无法知道属性已更改。

    【讨论】:

      【解决方案5】:

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

      注意:我的 INotifyPropertyChanged 编码正确。


      在我看来,我有

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

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

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

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

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

      如何连接是另一个问题,但是当我删除之前实例化另一个“未使用”的有问题的 xaml(在此答案的顶部)时ViewModel 的实例,视图将根据 INotifyPropertyChanged 机制进行更新。

      【讨论】:

      • 感谢上帝的这篇文章。我一直在努力寻找似乎永远试图弄清楚如何阻止 WPF 创建每个视图模型对象的额外实例,并在每次我交换视图时调用每个 vm 对象的 ctor。我以为我已经这样做了,但我还是决定尝试一下,以防万一,效果很好。不知道你为什么被否决,但谢谢你
      【解决方案6】:

      在我的情况下,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));
          }
          ...
      

      【讨论】:

        【解决方案7】:

        当您调用 OnPropertyChanged 时,请确保包含属性名称。今天花了我几个小时,这该死的隐藏绑定魔法太令人沮丧了。给我一条错误消息,或者其他东西,而不是默默地失败!

        因此,与其只调用 OnPropertyChanged() 而不提供参数,不如在您的属性设置器中调用它(以便 CallerMemberName 为您填充它),或者自己提供。

        例如在 xaml 的某个地方你有绑定:

        ... Value="{Binding Progress}" ...
        

        然后在代码隐藏中,您拥有从 INotifyPropertyChanged 继承的 DataContext 对象,并在更新您调用的值后某处的方法中:

        OnPropertyChanged("Progress");
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-26
          • 2020-09-21
          • 2013-10-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多