2013-05-23 7 views
0

Вот мой 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. Пожалуйста, помогите ...

ответ

0

синтаксиса для связывания с прикрепленной собственностью будет:

<TextBlock Text="{Binding Path=(t.DataGridColumns.ColumnBindingPath)}"/> 

В Path= должны быть написано явно при связывании с присоединенными свойствами. Это было исправлено в WPF 4.5, так что это может быть достаточно, чтобы написать

<TextBlock Text="{Binding (t.DataGridColumns.ColumnBindingPath)}"/> 

Обратите внимание, что вам все еще нужно скобку вокруг собственности. Это уже ответит на ваш вопрос?

+0

Это не работает. Raised System.Windows.Markup.XamlParseException. Сообщение = укажите значение «System.Windows.Baml2006.TypeConverterMarkupExtension». – user2398652

+0

Попробуйте <Содержимое ярлыка = {...} /> и проверьте, находятся ли все свойства, которые вы установили, в правильном формате. Сообщение означает, что некоторое значение свойства имеет неправильный формат. – Marc

Смежные вопросы