首页 > 解决方案 > 将自定义属性从 viewmodel 添加到 Datagrid

问题描述

我想在实现 INotifyPropertyChanged 的​​ ViewModel 中创建自定义属性并将该属性绑定到数据网格。

所以这个想法是(例如)我在 Model 中有 FirstName 和 LastName 字符串属性,我想在 ViewModel 中创建属性 FullName = FirstName + " " + LastName (我不想在 Model 类中这样做!),我想要在我有 FirstName、LastName 和 FullName 列的数据网格中绑定此属性

这是我的模型类:

    class User
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        //....
    }

视图模型:

class ViewModelUsers : ViewModelBase
    {
        public ObservableCollection<Models.User> Users { get; private set; }

        string _FlllName;
        public string FullName
        {
            //...
        }



        public ViewModelUsers()
        {
            //....
        }

还有我的 xaml:

        <DataGrid ItemsSource="{Binding Users}"
                  AutoGenerateColumns="False"
                  >
            <DataGrid.Columns>
                <DataGridTextColumn Header="First name" Binding="{Binding FirstName, Mode=OneWay}" Width="Auto"></DataGridTextColumn>
                <DataGridTextColumn Header="Last name" Binding="{Binding LastName, Mode=OneWay}" Width="Auto"></DataGridTextColumn>
                <DataGridTextColumn Header="Full name" Binding="{Binding Path=FullName, Mode=OneWay}" Width="Auto"></DataGridTextColumn>

这段代码不完整,还有更多行,但我希望你能理解我想要实现的目标。我是这个 c#-WPF (mvvm) 的新手,所以据我了解 Model.cs 应该是“干净的”,并且所有逻辑都应该在 viewModel 中。ViewModel 继承了实现 INotifyPropertyChanged 的​​ ViewModelBase。

正如我所说,我对此并不陌生,我正在寻找实施 MVVM 的最佳实践并在我进行中学习。

标签: c#wpfmvvm

解决方案


当您只需要显示全名时,您可以使用 aMultiBinding和 a IMultiValueConverter来连接值。

<DataGrid ItemsSource="{Binding Users}"
          AutoGenerateColumns="False">
  <DataGrid.Columns>
    <DataGridTextColumn Header="First name"
                        Binding="{Binding FirstName}" />
    <DataGridTextColumn Header="Last name"
                        Binding="{Binding LastName}" />
    <DataGridTextColumn Header="Full name">
      <DataGridTextColumn.Binding>
        <MultiBinding Converter="{StaticResource NameMultiValueConverter}">
          <Binding Path="FirstName" />
          <Binding Path="LastName" />
        </MultiBinding>
      </DataGridTextColumn.Binding>
    </DataGridTextColumn>
  </DataGrid.Columns>
</DataGrid>

IMultiValueConverter连接
每个数据项的名字和姓氏:

public class NameMultiValueConverter : IMultiValueConverter
{
  public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    return String.Format("{0} {1}", values[0], values[1]);
  }

  /// <inheritdoc />
  public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}

关于 MVVM,我想说该模型不应该是“干净的”。
根据定义,模型与视图没有关系或关联。视图模型将视图与模型分离。该模型包含业务实体和业务逻辑。

如果您想避免从视图到模型的任何依赖关系,您应该考虑将模型实体包装到视图可以绑定或模板的视图模型数据结构中。如果您严格遵循 MVVM 并且关心依赖关系(在类或程序集级别),您将不会在视图中使用数据业务模型。

模型当然可以实现接口INotifyPropertyChanged(它只公开一个事件PropertyChanged),但它不应该是针对视图的绑定的源。
虽然您可以InotifyPropertyChanged在模型上实现,但观察者向模型添加专用事件可能更方便。

因此,与其引发无意义的PropertyChanged事件(例如,如果计算完成并且CalculationResult设置了值),不如提高事件处理和引发CalculationCompleted事件的代码可读性。的处理程序PropertyChanged总是需要按名称过滤正确的属性,并在每次属性更改时调用。仅引发专门的事件,并且仅在特定事件上调用其处理程序。


推荐阅读