【问题标题】:Displaying data differntly across viewmodels, without changing model data跨视图模型以不同方式显示数据,而不更改模型数据
【发布时间】:2010-11-18 16:59:23
【问题描述】:

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

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

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

场景:

我有一个模型,只包含一个整数。

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

我有两个子视图模型,合并在父视图模型中,都显示这个整数。在其中一个视图模型上,我有一个命令,将整数的值增加 1。该值在模型中发生更改,它实现了 INotifyPropertyChanged,因此使第二个视图模型知道更改,因此它可以相应地更新。

到目前为止一切正常。

但是,我对一项新功能很感兴趣,但我无法让它发挥作用。说,我在我的第二个视图模型上想要显示整数,但我想改变数据的显示方式。然而,这应该在不改变模型中的数据的情况下完成。如果模型中的数据发生变化,转换后的数据也会随之变化。

例如,假设整数为 5。在第二个视图模型上,我想显示整数 + 2,即 7。 然后数据从第一个viewmodel变成6,也就是说第二个viewmodel上的属性会自动变成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);
        }
    }

主视图模型

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; }

    }



}

这是 ChildViewmodel 将自身绑定到 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}" />

再次,我希望能够在视图模型上创建第二个属性,它显示转换后的数据,基于但不更改原始数据,并且与正在更新的数据一起更新。 最好是一种converter-method,将数据转换成新的数据。

希望您能提供帮助。

【问题讨论】:

    标签: c# wpf mvvm transformation


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢,我会马上调查的。我使用更多视图模型的原因是主视图模型有一个选项卡控件,而每个子视图模型是一个不同的选项卡。它们都共享相同的数据源,但它们显示数据的方式不同。
    【解决方案2】:

    使用 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,但如果需要,您可以硬编码该值。可能还想为您的转换器添加一些检查,因为如果类型不正确,它将引发异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-06
      • 2018-08-29
      • 2013-08-22
      • 2013-02-17
      相关资源
      最近更新 更多