【发布时间】:2014-06-18 10:19:17
【问题描述】:
我有一个数据网格,其中列被动态填充。我必须在代码中执行此操作,因为用户可以通过自定义列设置系统添加列/删除列/修改列属性。
我创建了一个附加属性作为依赖属性,如下所示:
public class DataGridColumnBehavior
{
public static readonly DependencyProperty ColumnsSourceProperty =
DependencyProperty.RegisterAttached("ColumnsSource",
typeof (ObservableCollection<ColumnDescriptor>),
typeof (DataGridColumnBehavior),
new UIPropertyMetadata(null, ColumnsSourcePropertyChanged));
private static void ColumnsSourcePropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
var dataGrid = source as DataGrid;
var columnDescriptors = e.NewValue as ObservableCollection<ColumnDescriptor>;
if (dataGrid != null && columnDescriptors != null && columnDescriptors.Any())
{
dataGrid.Columns.Clear();
columnDescriptors.ToList().ForEach(col =>
{
var gridColumn = CreateDataGridColumn(col);
if(gridColumn != null)
dataGrid.Columns.Add(gridColumn);
});
}
}
private static DataGridColumn CreateDataGridColumn(ColumnDescriptor columnDescriptor)
{
Type propertyType = null;
if (columnDescriptor.ParentDtoType != null)
propertyType = columnDescriptor.ParentDtoType.GetProperty(columnDescriptor.DataPropertyName).PropertyType;
DataGridBoundColumn returnColumn;
if (propertyType == typeof (bool))
{
returnColumn = new DataGridCheckBoxColumn();
}
else if (propertyType == typeof (string) && columnDescriptor.LookupOn)
{
returnColumn = new DataGridLookupColumn();
}
else if (propertyType == typeof (DateTime?) || propertyType == typeof(DateTime))
{
returnColumn = new DataGridDateColumn();
}
else
{
returnColumn = new DataGridTextColumn();
}
returnColumn.Header = columnDescriptor.HeaderText;
returnColumn.Width = columnDescriptor.Width;
returnColumn.Binding = new Binding(columnDescriptor.DataPropertyName) { UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, Mode = BindingMode.TwoWay };
returnColumn.IsReadOnly = columnDescriptor.TextReadOnly;
returnColumn.Visibility = columnDescriptor.Visible ? Visibility.Visible : Visibility.Collapsed;
return returnColumn;
}
public static void SetColumnsSource(DependencyObject element, ObservableCollection<DataGridColumn> value)
{
element.SetValue(ColumnsSourceProperty, value);
}
public static ObservableCollection<DataGridColumn> GetColumnsSource(DependencyObject element)
{
return (ObservableCollection<DataGridColumn>)element.GetValue(ColumnsSourceProperty);
}
XAML:
<DataGrid Grid.Column="6" Grid.ColumnSpan="5" Grid.RowSpan="5" Grid.Row="8" Name="KorlistaDataGrid" MaxHeight="106" behavior:DataGridColumnBehavior.ColumnsSource="{Binding ColumnsListView}" ItemsSource="{Binding MyObservableCollection}" SelectedItem="{Binding ListViewSelectedItem, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" AutoGenerateColumns="False">
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Header="XXX" Command="{Binding ContextMenuCommand}" IsEnabled="{Binding CMSIsEnabled, UpdateSourceTrigger=PropertyChanged}"></MenuItem>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
我的自定义列:
public class DataGridDateColumn : DataGridTextColumn
{
protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
{
var dataGridBoundColumn = cell.Column as DataGridBoundColumn;
var datePicker = new DatePicker { Width = 50, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center };
if (dataGridBoundColumn != null)
{
datePicker.SetBinding(TextBox.TextProperty, dataGridBoundColumn.Binding);
var bindingExpression = datePicker.GetBindingExpression(TextBox.TextProperty);
if (bindingExpression != null)
{
bindingExpression.UpdateSource();
bindingExpression.UpdateTarget();
}
}
return datePicker;
}
}
一切看起来都很棒,我的列就像我想要的一样,我的 itemssource 中的所有绑定值都符合预期。
最后是我的问题:如何在此处配置绑定以便:
- 绑定值显示在我的日期选择器中的编辑模式中
- 如果我在编辑模式中更改值(手动或通过选择器),我显然希望在我的数据源中更新该值,并在我离开编辑模式后在视图模式中显示。
提前致谢!
【问题讨论】: