【问题标题】:How to tell UI that a bound WPF property, changed within the model, has updated如何告诉 UI 在模型中更改的绑定 WPF 属性已更新
【发布时间】:2013-06-21 19:32:42
【问题描述】:

我是 WPF 的新手,我尽可能地遵循 MVVM 模式。到目前为止一切顺利,除了我在绑定模型中的某些属性时遇到了问题。

因此,我在模型中公开了非静态属性,但它们只能在模型内部进行更改。我运行了一些功能,它做了很多事情,它通过我公开的一系列参数来跟踪它在做什么。

当我在 ViewModel 中有属性时我很好 - 我可以更新这些,因为我已经实现了 INotifyPropertyChanged。我已经看到有时人们也在他们的模型中实现了这一点,所以我尝试了,但不知道 INotifyPropertyChanged 是如何真正工作的/p>

我试图在我的 ViewModel 中创建一个从 Model 读取的属性,并将 xaml 绑定到此属性,但是因为我无法从 ViewModel 更改它,我遇到了告诉 UI 它已更改的相同问题.目前我在尝试解决这个问题时直接绑定,但我的目标是能够绑定到 ViewModel 中的一个属性,该属性只是从模型中获取值。

谁能给我一个很好的简单示例,说明单向绑定到基本控件(如标签/文本块等),当模型内部发生变化时会自行更新?

为了完整起见,这里是我所拥有的示例 xaml 的简化版本(显示绑定到模型属性和绑定到来自 ViewModel 的属性)。绑定有效,因为如果我对模型进行更改,它们会出现在设计器和初始构建中。

该模型是我自己的代码,我可以添加/删除任何内容以使其正常工作。也许这相当简单,但我目前没有看到解决方案,也没有在论坛上看到任何对我有意义的东西。

谢谢!

在模型中

public enum TempValues { zero, pos10, pos50, pos100 }
namespace AutoCalModel
{
    public class AutoCalibration : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }


        private TempValues _TempRelayValue = TempValues.zero;
        public TempValues TempRelayValue 
        {
            get { return _TempRelayValue; }
            set
            {
                if (!value.Equals( _TempRelayValue))
                {
                    _TempRelayValue = value;
                    NotifyPropertyChanged("TempRelayValue");
                }
            }
        }

        // rest of class including code that changes the above TempRelayValue
        // accessed through the public property only

    }    
}

在xml中

<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
    <TextBlock Name="labelPrsTitle" Text="Prs:" Margin="2,0,2,0"/>
    <TextBlock Name="labelPrsValue" Text="{Binding Path=currentPrsValueString, Mode=OneWay}" Margin="2,0,5,0"/>
    <Separator Margin="5,0,5,0"/>
    <TextBlock Text="Temp Relay:" Margin="5,0,2,0"/>
    <TextBlock Text="{Binding Path=TempRelayValue, Converter={StaticResource tempValuesConverter}, Mode=OneWay}" Margin="2,0,5,0">
        <TextBlock.DataContext><Model:AutoCalibration/></TextBlock.DataContext>
    </TextBlock>
</StackPanel>

【问题讨论】:

  • 如果您尝试使用 MVVM,那么您绝对不应该将您的视图 (XAML) 直接绑定到模型!您似乎完全错过了视图模型部分。 MVVM 有很多很棒的例子,所以不妨去看看它们。一个开始的地方msdn.microsoft.com/en-us/library/gg405484(v=pandp.40).aspx
  • 也许我不明白,但您正在创建AutoCalibration新实例,并将其分配给TextBlock 的DataContext。是否有任何代码稍后引用和修改该实例?
  • 您对 MVVM 中的“模型”有何解释?当 TempRelayValue 属性更改时,您的代码中发生了什么?有什么改变它吗?当你已经有一个应该绑定的视图模型时,为什么要这样绑定?
  • @DaveWilliams 澄清了一个问题,说我最初将它绑定到 ViewModel 但仍然卡住并尝试了我目前将它绑定到模型。在试图弄清楚这一点时,分离度减少了。我以后会“拉回来”!感谢您提供链接,看看我是否可以在那里找到解决方案。
  • @slugster 看我上面对戴夫威廉姆斯的评论

标签: c# wpf xaml


【解决方案1】:

我的一个朋友也犯了同样的错误。

  // rest of class including code that changes the above **_TempRelayValue**

在这里您已经决定您将更改 _tempRelayVALue 变量。变量没有任何与之关联的通知。所以你需要做的是通过如下的属性设置值,这应该通知 UI 模型或 VM 值已经改变。因为您已将通知实施到不在变量中的属性中。

TempRelayValue  = yourvalues;

【讨论】:

  • 对不起,但没有通过私有变量更改 TempRelayValue,而是通过公共属性完成所有操作。那是一个错字。我已经改变了它并澄清了这个问题。仍然感谢您指出这一点!
  • 好的。我认为您在绑定中使用的实例以及代码中的实例误导了您。您是否在代码中创建新实例并尝试设置值。?
  • 只创建了单个实例(如我所见)。请参阅我在问题下对 Clemens 所做的评论。在创建模型的 4 个实例之前,我确实陷入了这个陷阱——当时很混乱,但后来我意识到,每次你在 DataContext 中提到模型时,它都会创建一个新的实例
  • 我对第一次实例化时设置的类有一个静态引用,以便在代码中每当我需要更改任何作为实例成员的东西时,我都会要求我已经拥有的实例成员之前创建的。否则我无法访问它。我没有在其他地方创建此类、代码或 xaml 的实例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-27
  • 2011-03-31
  • 2018-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多