首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MVVM:绑定变更模型

MVVM:绑定变更模型
EN

Stack Overflow用户
提问于 2019-04-26 18:41:38
回答 1查看 47关注 0票数 0

我有某种背景任务,它定期执行,或者有人手动启动它。

现在,我需要某种进步/结果视图,它显示已处理的数据。这个窗口应该一直显示出来。

问题是,每次后台任务启动时都会创建数据模型的一个新实例。那么,即使恢复了模型,如何保持Model -> ViewModel的绑定?

我创建了一些非常基本的示例,作为展示:

视图:

代码语言:javascript
复制
<Window x:Class="View.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:View"
    mc:Ignorable="d"
    Title="MainWindow" Height="200" Width="300" Background="Black">
<Grid>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Label Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Foreground="White" HorizontalAlignment="Center" Content="{Binding MainModelText}"/>
    </Grid>
</Grid>

ViewModel:

代码语言:javascript
复制
public class ViewModel : INotifyPropertyChanged
{
    MainModel _MainModel;

    string _MainModelText;
    public string MainModelText
    {
        get { return this._MainModelText; }
        set
        {
            this._MainModelText = value;
            OnNotifyPropertyChanged("MainModelText");
        }
    }

    public ViewModel(MainModel mainModel)
    {
        this._MainModel = mainModel;
        this._MainModel.PropertyChanged += _MainModel_PropertyChanged;

    }

    private void _MainModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if(string.Equals(e.PropertyName, "SomeText"))
        {
            this.MainModelText = _MainModel.SomeText + new Random().Next(1000);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnNotifyPropertyChanged(string propName)
    {
        if(this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

模型:

代码语言:javascript
复制
public class MainModel : INotifyPropertyChanged
{
    string _SomeText;
    public string SomeText
    {
        get { return this._SomeText; }
        set
        {
            this._SomeText = value;
            OnNotifyPropertyChanged("SomeText");
        }
    }

    public MainModel()
    {
        this.SomeText = "Its MainModel!";
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnNotifyPropertyChanged(string propName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

Business-Logic

代码语言:javascript
复制
public class Logic
{
    MainModel _MainModel;
    View.MainWindow _Window;

    public Logic()
    {
        this._MainModel = new MainModel();
        _Window = new View.MainWindow(new ViewModel(_MainModel));
    }

    public void Start()
    {
        _Window.ShowDialog();
    }

    public void NewAll()
    {
        this._MainModel = new MainModel();
        //working...
        this._MainModel.SomeText = "Finished";
    }
}

因此,显然“已完成”没有显示在窗口上,因为它被设置为另一个MainModel实例。

那么如何在ViewModel中更新模型引用呢?像这样的事情有什么最佳实践?

编辑:

代码语言:javascript
复制
public class Logic
{
    MainModel _MainModel;
    ViewModel _ViewModel;
    View.MainWindow _Window;

    public Logic()
    {
        this._MainModel = new MainModel();
        this._ViewModel = new ViewModel(this._MainModel);
        _Window = new View.MainWindow(this._ViewModel);
    }

    public void Start()
    {
        _Window.ShowDialog();
    }

    public void NewAll()
    {
        this._MainModel = new MainModel();
        this._ViewModel.Reload(this._MainModel);
        //working...
        this._MainModel.SomeText = "Finished";
    }
}

在VM中添加:

代码语言:javascript
复制
internal void Reload(MainModel mainModel)
{
    this._MainModel = mainModel;
    this._MainModel.PropertyChanged -= _MainModel_PropertyChanged;
    this._MainModel.PropertyChanged += _MainModel_PropertyChanged;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-27 18:42:29

除非您有充分的理由不通过VM属性提供MainModel,否则我建议您这样做。然后,您可以跳过SomeText属性并直接绑定到Model.SomeText,因为您的模型已经实现了INotifyPropertyChanged。

如果您想加载一个全新的Model实例,那么可以直接在VM属性上设置它。

如果您不想为视图提供完整的模型,那么您的方法就有效了。但是,我也会从模型构造函数调用ReloadModel,因此您可以将代码放在一个位置。另外,您应该将PropertyChanged事件从oldModel中取消注册,而不是在您已经将它更新到新模型之后(首先检查_mainModel == null )。

在PropertyChanged调用中,考虑使用nameof(SomeProperty)而不是像现在这样固定的字符串"SomeProperty“。如果您要在某个时候重命名该属性,那么代码就不会中断。

看看MVVM,这个框架可以让您避免一遍又一遍地编写一些样板代码,他们提供的Messenger是从Model到VM信号的好方法。它将这个示例简化为几行。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55873325

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档