2017-02-11 5 views
0

Мне нужно изменить datagrid, чтобы каждый заголовок столбца имел текстовое поле, поле со списком и флажок, и все они должны быть привязаны к свойству. Я потратил много времени, пытаясь реализовать это с помощью DataGrid по умолчанию, но я не думаю, что это возможно, поэтому я решил создать пользовательский DataGrid.Как связать собственные столбцы datagrid

До сих пор у меня есть связанное свойство BindableColumns, которое хранит DataTable, поэтому у меня есть данные, которые мне нужно отображать. Проблема в том, что я не знаю, как передать эти данные OnAutoGeneratedColumns, поэтому я могу добавить столбцы в Columns свойство DataGrid.

public class BindableGrid : DataGrid 
{ 
    public DataTable BindableColumns 
    { 
     get { return (DataTable)GetValue(BindableColumnsProperty); } 
     set { SetValue(BindableColumnsProperty, value); } 
    } 

    public static readonly DependencyProperty BindableColumnsProperty = 
     DependencyProperty.Register("BindableColumns", typeof(DataTable), typeof(BindableGrid), new PropertyMetadata(null, BindableColumnsPropertyChanged)); 

    private static void BindableColumnsPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) 
    { 
     // This is where I get DataTable after binding 
    } 


    protected override void OnAutoGeneratedColumns(EventArgs e) 
    { 
     // This is where I need the DataTable to generate columns. 
     // I don't know how to invoke this method myself. 
     Columns.Add(new DataGridTemplateColumn 
     { 
      Header = "Test1", 
      HeaderTemplate = new DataTemplate() 
     }); 
    } 
} 

И XAML:

<controls:BindableGrid ItemsSource="{Binding Data}" BindableColumns="{Binding Data}" AutoGenerateColumns="True"> 
</controls:BindableGrid> 

EDIT:

Благодаря @Ramin я рабочие колонны. У меня возникли проблемы с динамическим добавлением строк, потому что DataGrid ожидает строки как класс с точно такими же именами переменных, что и привязки столбцов. Для тех, кто возникли проблемы, вот как я ее решил:

for (var rowIndex = 0; rowIndex < data.Rows.Count; rowIndex++) 
{ 
    dynamic row = new ExpandoObject(); 

    for (var i = 0; i < data.Columns.Count; i++) 
    // Create variables named after bindings, and assign values 
     ((IDictionary<string, object>)row)[data.Columns[i].ColumnName.Replace(' ', '_')] = data.Rows[rowIndex].ItemArray[i]; 

    // Add row to DataGrid 
    dg.Items.Add(row); 
} 

ответ

1

Что касается источника проблемы, вот DataGrid с шаблонного заголовком, который содержит TextBox, ComboBox и CheckBox:

<DataGrid > 
     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding}" > 
       <DataGridTextColumn.HeaderTemplate> 
        <DataTemplate> 
         <StackPanel Orientation="Horizontal"> 
          <TextBox Text="{Binding DataContext.Name, RelativeSource={RelativeSource AncestorType=DataGrid}}" /> 
          <CheckBox IsChecked="{Binding DataContext.Value , RelativeSource={RelativeSource AncestorType=DataGrid}}"/> 
          <ComboBox ItemsSource="{Binding DataContext.Names , RelativeSource={RelativeSource AncestorType=DataGrid}}" SelectedIndex="0"/> 
         </StackPanel> 
        </DataTemplate> 
       </DataGridTextColumn.HeaderTemplate> 
      </DataGridTextColumn> 
     </DataGrid.Columns> 
    </DataGrid> 

DataContext использует пользовательский класс:

public MainWindow() 
{ 
    InitializeComponent(); 
    DataContext = new MyClass() { Name = "Name0", Value = true, Names = new string[2] { "Name1", "Name2" } }; 
} 

public class MyClass 
{ 
    public string Name { get; set; } 
    public bool Value { get; set; } 
    public string[] Names { get; set; } 
} 

EDIT

вы можете динамически добавлять столбцы:

public void addNewColumn(Header h, string bindcol) 
    { 
     DataGridColumn col = new DataGridTextColumn(){Binding=new Binding(bindcol)}; 
     col.Header = h; 
     col.HeaderTemplate = (DataTemplate)FindResource("dgh") as DataTemplate; 
     dg.Columns.Add(col); 
    } 

в App.xaml:

<Application.Resources> 
    <DataTemplate x:Key="dgh"> 
     <StackPanel Orientation="Horizontal"> 
      <TextBox Text="{Binding Name}" /> 
      <CheckBox IsChecked="{Binding Value}"/> 
      <ComboBox ItemsSource="{Binding Names}" SelectedIndex="0"/> 
     </StackPanel> 
    </DataTemplate> 
</Application.Resources> 

Для испытаний (при условии, что есть DataGrid с именем дециграмм):

public MainWindow() 
    { 
     InitializeComponent(); 
     var h1 = new Header() 
     { 
      Name = "Name0", 
      Value = true, 
      Names = new string[2] { "Name1", "Name2" } 
     }; 
     var h2 = new Header() 
     { 
      Name = "Name1", 
      Value = true, 
      Names = new string[2] { "Name12", "Name22" } 
     }; 

     addNewColumn(h1, "col1"); 
     addNewColumn(h2, "col2"); 

    } 

    public class Header 
    { 
     public string Name { get; set; } 
     public bool Value { get; set; } 
     public string[] Names { get; set; } 
    } 

Обратите внимание, что «col1» и «col2» относятся к элементу Itemssource datagrid.

+0

Будет ли это работать для массива столбцов? Потому что я не знаю, сколько столбцов у меня будет в моей «DataTable». Я разрешаю пользователю загружать файлы csv, которые преобразуются в 'DataTable', поэтому количество столбцов различно для каждого файла. – FCin

+0

см. Отредактированную часть. – Ron

+0

Я почти получил его на работу, но я не могу динамически добавлять строки из-за привязки. 'dg.Items.Add();' требует объект со свойствами, названный так же, как привязки, но в C# я не могу динамически создавать классы. – FCin