跨视图模型显示不同的数据,而不更改模型数据

时间:2010-11-18 16:59:23

标签: c# wpf mvvm transformation

最近另一个问题一直困扰着我,我很确定这是我缺乏WPF / MVVM技能阻止我看到明显的问题。我确信解决方案很简单,但我不确定如何实现它。

我正在使用WPF / C#开发,我正在使用MVVM设计模式。

为简单起见,我将问题归结为最基本的组件。

情景:

我有一个Model,只包含一个整数。

我有一个父ViewModel,显示这个整数。

我有两个子视图模型,在父视图模型中包含,都显示这个整数。在其中一个viewmodel上,我有一个Command,用1递增整数的值。模型中的值发生了变化,实现了INotifyPropertyChanged,从而使第二个ViewModel知道了这个变化,因此可以相应地更新。

到目前为止一切正常。

但是,我对一个新功能很感兴趣,我无法让它工作。说,我在我的第二个视图模型上想要显示整数,但我想改变数据的显示方式。但是,这应该在不更改模型中的数据的情况下完成。如果模型中的数据发生变化,转换的数据将相应地改变。

作为一个例子,假设整数是5.在第二个视图模型中,我想显示整数+ 2,意思是7。 然后,数据从第一个视图模型更改为6,这意味着第二个视图模型上的属性会自动更改为8.

这是如何实现的?

一些代码,用于说明目前系统的外观:

模特:

public DataModel()
{
    data = new Data();

    data.Value = 2;
}

public Data data { get; set; }

数据类:

public class Data :  INotifyPropertyChanged
{
    private int m_Value;
    public int Value
    {
        get { return m_Value; }
        set
        {
            if (m_Value != value)
            {
                m_Value = value;
                OnPropertyChanged("Value");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {

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

mainviewmodel

public class MainViewModel : ViewModelBase
{
    readonly DataModel _dataModel;

    public MainViewModel()
    {
        _dataModel = new DataModel();

        ViewModel1 = new 1ViewModel(this);
        ViewModel2 = new 2ViewModel(this);
    }


    public 1ViewModel ViewModel1 { get; set; }

    public 2ViewModel ViewModel2 { get; set; }

    public Data Data
    {
        get { return _dataModel.data; }

    }



}

以下是ChildViewmodels将自己绑定到Data对象的方式

public class 1ViewModel : ViewModelBase
{

    private MainViewModel _mainViewModel;

    public 1ViewModel(MainViewModel mainViewModel)
    {
        _mainViewModel = mainViewModel;

    }

    public Data Number
    {
        get { return _mainViewModel.data; }

    }

}

在view1上,我像这样绑定了Number属性

<TextBlock  Text="{Binding Path=Number.Value}" />

同样,我希望能够在viewmodel上创建第二个属性,该属性基于但不更改原始数据显示已转换的数据,并且与正在更新的数据一起更新。 优选地,它应该是一种转换器方法,它将数据转换为新数据。

希望你能提供帮助。

2 个答案:

答案 0 :(得分:1)

ViewModel应该准备好显示数据,但不知道它的显示方式。如果您想要更改数据在View中的显示方式,那么您将使用Converter。这将允许您为多个视图使用相同的ViewModel并具有不同的外观。

此外,将ViewModel包装在ViewModel中并不一定是您想要的方式。 ViewModel通常具有关联的View。如果您没有查看ViewModel,请将数据视为典型类,然后继续使用单个ViewModel。

答案 1 :(得分:0)

使用IValueConverter:

public class AddConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (int)value + (int)parameter;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (int)value - (int)parameter;            
    }
}

在您的XAML中,添加资源:                   

并更新你的绑定:     

我在这里使用了ConverterParameter,但如果需要,您可以对值进行硬编码。可能还想在转换器中添加一些检查,因为如果类型不正确,它会抛出异常。