Вот мой ViewModel класс:Bindable динамического DataGrid Столбцы
public class ColumnViewModel : ViewModelBase
{
private string bindingPropName;
public string BindingPropName
{
get { return bindingPropName; }
set
{
if (bindingPropName != value)
{
bindingPropName = value;
RaisePropertyChanged("BindingPropName");
}
}
}
private string header;
public string Header
{
get { return header; }
set
{
if (header != value)
{
header = value;
RaisePropertyChanged("Header");
}
}
}
}
DataGrid расширение классы:
public static class DataGridColumns
{
static DataGridColumns()
{
FrameworkElement.DataContextProperty.AddOwner(typeof(DataGridTextColumn));
}
private static readonly DependencyProperty DataGridColumnSettingsProperty = DependencyProperty.RegisterAttached(
"DataGridColumnSettings",
typeof(DataGridColumnSettings),
typeof(DataGridColumn));
private static void SetDataGridColumnSettings(DataGridColumn column, DataGridColumnSettings settings) { column.SetValue(DataGridColumnSettingsProperty, settings); }
private static DataGridColumnSettings GetDataGridColumnSettings(DataGridColumn column) { return column.GetValue(DataGridColumnSettingsProperty) as DataGridColumnSettings; }
public static readonly DependencyProperty DisplayColumnsProperty = DependencyProperty.RegisterAttached(
"DisplayColumns",
typeof(IList),
typeof(DataGridColumns),
new PropertyMetadata(null, DisplayColumnsPropertyChanged));
public static void SetDisplayColumns(DataGrid dataGrid, IList columns) { dataGrid.SetValue(DisplayColumnsProperty, columns); }
public static IList GetDisplayColumns(DataGrid dataGrid) { return dataGrid.GetValue(DisplayColumnsProperty) as IList; }
private static void DisplayColumnsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = d as DataGrid;
var columns = e.NewValue as IList;
var template = GetColumnSettingsTemplate(target);
CreateColumns(target, columns, template);
}
public static readonly DependencyProperty ColumnSettingsTemplateProperty = DependencyProperty.RegisterAttached(
"ColumnSetupTemplate",
typeof(DataTemplate),
typeof(DataGridColumns),
new PropertyMetadata(null, ColumnSettingsTemplateChanged));
public static void SetColumnSettingsTemplate(DataGrid dataGrid, DataTemplate columnSetupTemplate) { dataGrid.SetValue(ColumnSettingsTemplateProperty, columnSetupTemplate); }
public static DataTemplate GetColumnSettingsTemplate(DataGrid dataGrid) { return dataGrid.GetValue(ColumnSettingsTemplateProperty) as DataTemplate; }
private static void ColumnSettingsTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = d as DataGrid;
var columns = GetDisplayColumns(target);
var template = e.NewValue as DataTemplate;
CreateColumns(target, columns, template);
}
private static void CreateColumns(DataGrid dataGrid, IList columnViewModels, DataTemplate columnSettings)
{
if (dataGrid == null)
return;
dataGrid.Columns.Clear();
if (columnViewModels == null)
return;
foreach (var column in columnViewModels)
{
var newColumn = new DataGridTextColumn();
newColumn.SetValue(FrameworkElement.DataContextProperty, column);
if (columnSettings != null)
{
var settings = columnSettings.LoadContent() as DataGridColumnSettings;
if (settings != null)
{
settings.Setup(newColumn, column);
SetDataGridColumnSettings(newColumn, settings);
}
}
dataGrid.Columns.Add(newColumn);
}
}
}
public class DataGridColumnSettings : FrameworkElement
{
public static readonly DependencyProperty ColumnBindingPathProperty = DependencyProperty.Register(
"ColumnBindingPath",
typeof(string),
typeof(DataGridColumnSettings),
new PropertyMetadata(null, ColumnBindingPathChanged));
public string ColumnBindingPath
{
get { return GetValue(ColumnBindingPathProperty) as string; }
set { SetValue(ColumnBindingPathProperty, value); }
}
private static void ColumnBindingPathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = d as DataGridColumnSettings;
if (target == null)
return;
target.column.Binding = new Binding(e.NewValue as string);
}
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
"Header",
typeof(object),
typeof(DataGridColumnSettings));
public object Header
{
get { return GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
private DataGridTextColumn column;
private object viewModel;
public void Setup(DataGridTextColumn column, object columnViewModel)
{
this.column = column;
viewModel = columnViewModel;
this.DataContext = columnViewModel;
if (Header is FrameworkElement)
{
(Header as FrameworkElement).DataContext = columnViewModel;
column.Header = Header;
}
else
BindingOperations.SetBinding(column, DataGridColumn.HeaderProperty, new Binding("Header") { Source = this });
column.Binding = new Binding(ColumnBindingPath);
}
}
и мой XAML код:
<DataGrid t:DataGridColumns.DisplayColumns="{Binding Columns}" ItemsSource="{Binding Rows}" AutoGenerateColumns="False">
<t:DataGridColumns.ColumnSettingsTemplate>
<DataTemplate>
<t:DataGridColumnSettings ColumnBindingPath="{Binding BindingPropName}">
<t:DataGridColumnSettings.Header>
<TextBlock Text="{Binding Header}"/>
</t:DataGridColumnSettings.Header>
</t:DataGridColumnSettings>
</DataTemplate>
</t:DataGridColumns.ColumnSettingsTemplate>
</DataGrid>
Все, что я пытаюсь достижение добавляет CellTemplate:
<DataGrid t:DataGridColumns.DisplayColumns="{Binding Columns}" ItemsSource="{Binding Rows}" AutoGenerateColumns="False">
<t:DataGridColumns.ColumnSettingsTemplate>
<DataTemplate>
<t:DataGridColumnSettings ColumnBindingPath="{Binding BindingPropName}">
<t:DataGridColumnSettings.Header>
<TextBlock Text="{Binding Header}"/>
</t:DataGridColumnSettings.Header>
<t:DataGridColumnSettings.CellTemplate>
<TextBlock Text="{Binding ColumnBindingPath}"/>
</t:DataGridColumnSettings.CellTemplate>
</t:DataGridColumnSettings>
</DataTemplate>
</t:DataGridColumns.ColumnSettingsTemplate>
</DataGrid>
Я думаю, что самым простым подходом было бы добавить еще одно свойство зависимостей, чтобы принять шаблон ячейки. Тогда, если это существует, создайте DataGridTemplateColumn вместо DataGridTextColumn при заполнении DataGrid, но у меня есть небольшая проблема с привязкой свойства CellBlayerBox к свойствам ColumnBindingPath. Пожалуйста, помогите ...
Это не работает. Raised System.Windows.Markup.XamlParseException. Сообщение = укажите значение «System.Windows.Baml2006.TypeConverterMarkupExtension». – user2398652
Попробуйте <Содержимое ярлыка = {...} /> и проверьте, находятся ли все свойства, которые вы установили, в правильном формате. Сообщение означает, что некоторое значение свойства имеет неправильный формат. – Marc