Wpf 应用程序中的注释和 UI 控件
Annotation and UI control within Wpf application
我有这个视图模型class
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>
我需要扩展数据网格的行为以使其更聪明我的意思是,我有这个模型class:
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
public DateTime DateNaissance { get; set; }
}
我需要向 class 属性添加一些属性,并使数据网格将其转换为 UI 控件:
例如:
[DatePicker]
public DateTime DateNaissance { get; set; }
会在绑定到DateNaissance
的datagrid中生成一列Datepicker。
我该怎么做?最好和更简单的方法是什么?
谢谢
您可以通过处理 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。
你的Student
class显然是模特。根据 MVVM,你不应该在你的 model 中定义它的 view 应该是什么样子(例如使用一些属性,比如 [DatePicker]
你的例子)。
您应该在 view 中定义它,而不是这个 - 在这种情况下就是 XAML 标记。为您的数据项创建一个 DataTemplate
并描述您想要拥有的所有 聪明 事物。
请看this article。有一个很好的例子,如何为自动生成的列灵活定义 DataTemplate
s。
你也可以考虑this Microsoft article。
此外,我建议您仔细阅读有关 MVVM 范式的内容。
我有这个视图模型class
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>
我需要扩展数据网格的行为以使其更聪明我的意思是,我有这个模型class:
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
public DateTime DateNaissance { get; set; }
}
我需要向 class 属性添加一些属性,并使数据网格将其转换为 UI 控件:
例如:
[DatePicker]
public DateTime DateNaissance { get; set; }
会在绑定到DateNaissance
的datagrid中生成一列Datepicker。
我该怎么做?最好和更简单的方法是什么?
谢谢
您可以通过处理 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。
你的Student
class显然是模特。根据 MVVM,你不应该在你的 model 中定义它的 view 应该是什么样子(例如使用一些属性,比如 [DatePicker]
你的例子)。
您应该在 view 中定义它,而不是这个 - 在这种情况下就是 XAML 标记。为您的数据项创建一个 DataTemplate
并描述您想要拥有的所有 聪明 事物。
请看this article。有一个很好的例子,如何为自动生成的列灵活定义 DataTemplate
s。
你也可以考虑this Microsoft article。
此外,我建议您仔细阅读有关 MVVM 范式的内容。