【问题标题】:Annotation and UI control within Wpf applicationWpf 应用程序中的注释和 UI 控制
【发布时间】:2015-02-28 20:32:33
【问题描述】:

我有这个视图模型类

 public  class SchoolViewModel : INotifyPropertyChanged
    {

      private  ObservableCollection<Student> _Eleves=  new ObservableCollection<Student>();

      public  ObservableCollection<Student> Eleves 
      {
          get {
              return _Eleves;
              }

          set {
              _Eleves = value;
              PropertyChanged(this, new PropertyChangedEventArgs("Eleves"));

          }
      }
      public SchoolViewModel( )
      {
      }


      public event PropertyChangedEventHandler PropertyChanged;
    }

我添加了这个简单的页面:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:SchoolViewModel x:Key="Locator" />
    </Window.Resources>
        <Grid  >
        <DataGrid  AutoGenerateColumns="True" ItemsSource="{Binding Eleves, Source={StaticResource Locator}}" ></DataGrid>
    </Grid>
</Window>

我需要扩展数据网格的行为以使其更聪明我的意思是,我有这个模型类:

 public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string FirstName { get; set; }
        public DateTime DateNaissance { get; set; }
    }

我需要在类属性中添加一些属性,并让 datagrid 将其转换为 UI 控件:

例如:

[DatePicker]
 public DateTime DateNaissance { get; set; }

会在绑定到DateNaissance的datagrid中生成一列Datepicker。

我该怎么做?最好和更简单的方法是什么?

谢谢

【问题讨论】:

    标签: c# wpf mvvm datagrid annotations


    【解决方案1】:

    您的Student 课程显然是一个模型。根据 MVVM,您不应该在 model 中定义其 view 的外观(例如,在您的示例中使用 [DatePicker] 等属性)。

    您应该在您的视图 中定义它而不是这个,这就是本例中的 XAML 标记。为您的数据项创建一个DataTemplate,并描述您想要拥有的所有聪明东西。

    请查看this article。有一个很好的例子,如何为自动生成的列灵活定义DataTemplates。

    你也可以考虑this Microsoft article

    另外,我建议您仔细阅读 MVVM 范例。

    【讨论】:

      【解决方案2】:

      你可以通过处理DataGrid.AutoGeneratingColumn来做到这一点。

      XAML:

      <DataGrid x:Name="myDataGrid"
                AutoGenerateColumns="True"
                AutoGeneratingColumn="OnDataGridAutoGeneratingColumn"
                ItemsSource="{Binding Eleves, Source={StaticResource Locator}}" />
      

      事件处理程序:

      private void OnDataGridAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
      {
          PropertyInfo propertyInfo;
          PropertyDescriptor propertyDescriptor;
          IEnumerable attributes;
      
          if ((propertyInfo = e.PropertyDescriptor as PropertyInfo) != null)
          { attributes = propertyInfo.GetCustomAttributes(); }
          else if ((propertyDescriptor = e.PropertyDescriptor as PropertyDescriptor) != null)
          { attributes = propertyDescriptor.Attributes; }
          else
          { return; }
      
          ColumnAttribute attribute = attributes
              .OfType<ColumnAttribute>()
              .FirstOrDefault();
      
          if (attribute != null)
          { e.Column = attribute.CreateColumn(myDataGrid, e.PropertyDescriptor); }
      }
      

      用于注释属性和创建 DataGridColumns 的属性:

      public abstract class ColumnAttribute : Attribute
      {
          protected internal abstract DataGridColumn CreateColumn(DataGrid dataGrid, object property);
      }
      
      public class DatePickerAttribute : ColumnAttribute
      {
          protected internal override DataGridColumn CreateColumn(DataGrid dataGrid, object property)
          {
              Binding binding = new Binding();
              DataGridDateColumn column = new DataGridDateColumn();
      
              column.Binding = binding;
      
              PropertyInfo propertyInfo;
              PropertyDescriptor propertyDescriptor;
      
              if ((propertyDescriptor = property as PropertyDescriptor) != null)
              {
                  binding.Path = new PropertyPath(propertyDescriptor.Name, null);
      
                  if (propertyDescriptor.IsReadOnly)
                  {
                      binding.Mode = BindingMode.OneWay;
                      column.IsReadOnly = true;
                  }
              }
              else if ((propertyInfo = property as PropertyInfo) != null)
              {
                  binding.Path = new PropertyPath(propertyInfo.Name, null);
      
                  if (!propertyInfo.CanWrite)
                  {
                      binding.Mode = BindingMode.OneWay;
                      column.IsReadOnly = true;
                  }
              }
      
              return column;
          }
      }
      

      最后是我们的专栏,里面有一个 DatePicker:

      public class DataGridDateColumn : DataGridBoundColumn
      {
          protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
          {
              TextBlock textBlock = new TextBlock();
              BindingBase binding = Binding;
      
              if (binding != null)
              { BindingOperations.SetBinding(textBlock, TextBlock.TextProperty, Binding); }
      
              return textBlock;
          }
      
          protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
          {
              DatePicker datePicker = new DatePicker();
              BindingBase binding = Binding;
      
              if (binding != null)
              { BindingOperations.SetBinding(datePicker, DatePicker.SelectedDateProperty, Binding); }
      
              return datePicker;
          }
      }
      

      注意:这不是 MVVM 解决方案,因为您注释模型的属性(在模型中指定视图)。如果您想要 MVVM 解决方案,请不要使用属性并根据属性类型选择 DataGridColumn。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-01
        • 2011-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-17
        相关资源
        最近更新 更多