【问题标题】:Prism 5.0 wrap Model Attributes in ViewModelPrism 5.0 在 ViewModel 中包装模型属性
【发布时间】:2016-12-08 16:51:56
【问题描述】:

您好,我对 Prism 比较陌生,但这是我的问题:

我目前正在使用带有 WPF 的 Prism 5。我创建了一个模型、视图模型和视图。当模型中的属性更改时,视图会更新。我的问题是:当我想处理模型中的属性(例如另一个属性名称)时,视图没有得到更新。这是我的代码。如果您能帮助我,我将非常感激。

当模型中的 RunTinting 发生变化时,视图没有得到更新。

型号

public class MyModel :BindableBase

{               
    private Boolean _RunTinting;
    public Boolean RunTinting
    {
        get { return _RunTinting; }
        set { SetProperty(ref _RunTinting, value); }
    }

视图模型

public class MainWindowViewModel : BindableBase
{

    private MyModel model;
    public MyModel Model
    {
        get { return this.model; }
        set { SetProperty(ref this.model, value); }
    }

    public MainWindowViewModel()
    {
        this.Model=new MyModel();

    }


    public Boolean RunTinting2
    {
        get { return this.model.RunTinting; }
        set { SetProperty(ref this._RunTinting, value); }
    }

 }

XAML

<Label x:Name="label1_Copy11" Content="{Binding RunTinting2}" HorizontalAlignment="Left" Margin="366,320,0,0" VerticalAlignment="Top" Height="25" Width="85" >

【问题讨论】:

  • 属性更改会触发属性更改的实例上的事件。这不会神奇地转移到暴露另一个对象属性的其他对象。

标签: c# wpf mvvm


【解决方案1】:

如果您动态设置 model 属性,则视图应绑定到此属性而不是视图模型属性:

<Label x:Name="label1_Copy11" Content="{Binding Model.RunTinting}" HorizontalAlignment="Left" Margin="366,320,0,0" VerticalAlignment="Top" Height="25" Width="85" >

因为当模型的属性设置为新值时,视图模型不会引发任何更改通知。

另一个选项是通过视图模型的 wrapper 属性设置模型属性,即不是直接设置模型属性,而是设置视图模型属性。确保随后在包装器属性的设置器中设置模型的属性,并为视图绑定到的视图模型属性引发 PropertyChanged 事件:

public class MainWindowViewModel : BindableBase
{
...
   public Boolean RunTinting2
  {
    get { return this.model.RunTinting; }
    set { this.model.RunTinting = value; OnPropertyChanged("RunTinting2"); }
  }
}

<Label x:Name="label1_Copy11" Content="{Binding RunTinting2}" HorizontalAlignment="Left" Margin="366,320,0,0" VerticalAlignment="Top" Height="25" Width="85" >

【讨论】:

  • 但是 Bindable 类中不是已经存在 propertychanged 事件吗?
  • 您能否提供一个可重现的示例,说明您当时如何以及在何处设置属性?您要么需要设置并绑定到模型属性,要么设置或绑定到视图模型属性。并在您设置的属性的设置器中引发 PropertyChanged 事件。
  • @user7268733 如果使用第二种解决方案,您需要将 PropertyChanged 事件处理程序连接到将更改事件复制到 ViewModel 的 model。例如,model.PropertyChanged 处理程序可能会说“if (e.PropertyName == "RunTinting") OnPropertyChanged("RunTinting2");` 以确保在 ViewModel 层上触发相同的更改事件。
【解决方案2】:

这就是我解决这个问题的方法,谢谢 Rachel 和 Will。

视图模型

    public void InitModel()
    {
        Model.PropertyChanged += Model_PropertyChanged;
    }

    private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "RunTinting")
        { 
            OnPropertyChanged("RunTinting2");
        }

    }

@mm8,我尝试了您的解决方案,但没有奏效……但无论如何感谢您花费的时间。

我不知道为什么我的回答有负面评价。它工作并尊重 mvvm 模型!

【讨论】:

  • 这不是一个好的解决方案,因为您正在混合模型和视图模型。 ViewModel 不应通过 INotifyPropertyChanged 通知 View。 ViewModel 类应该继承自 BindableBase,Model 应该是 POCO。如果您通过某种形式的 ORM(例如 EF 或 Dapper)创建和加载对象数据,您将遇到性能和线程问题。
  • Viewmodel 继承自 BindableBase,model 也是如此。这可以通过 Prism 框架实现。您可以查看 Prism 的示例项目。
  • 作为 Prism 和 MVVM 的长期实践者 - 无论他们的示例显示什么,您都不应该这样做。
  • toadflakz 您能否详细说明性能和线程问题。正如您所说的 POCO 模型必须更新视图模型,这可以通过 BindableBase 完成。您是否改为实施 INotifyPropertyChange。 (Bindablebase 已经实现了 INotifyPropertyChange)
  • PropertyChanged 只能在 Dispatcher 线程上处理。如果您在后台线程上加载或修改通知对象,UI 将不会收到更改通知。如果您加载 100 行并且 Model 对象上的每个属性都会引发通知,那么您将无缘无故地引发 100 多个额外事件 - 这可能并且确实会导致性能随着时间的推移而下降,特别是如果您链接其他属性中的更改基于通知。 Model 对象应该只用于封装数据,ViewModel 用于绑定到 View 并监控变化,View 用于呈现数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多