2017-02-11 58 views
0

我需要修改数据网格,以便每个列标题都有一个文本框,组合框和复选框,并且所有这些都必须绑定到属性。我花了很多时间试图用默认的DataGrid实现这个,但我不认为这是可能的,所以我决定创建一个自定义的DataGrid。如何绑定自定义数据网格列

到目前为止,我有一个可绑定的属性BindableColumns,它存储了DataTable,所以我有我需要显示的数据。问题是我不知道如何将这些数据传递给OnAutoGeneratedColumns,所以我可以在DataGridColumns属性中添加列。

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> 

编辑:

感谢@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:

<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; } 
} 

编辑

你可以动态地添加列:

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 DG):

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。

+0

这将工作的列数组?因为我不知道我的'DataTable'中有多少列。我让用户加载转换为“DataTable”的csv文件,因此每个文件的列数是不同的。 – FCin

+0

参见编辑的部分。 – Ron

+0

我几乎可以正常工作,但由于绑定,我无法动态添加行。 'dg.Items.Add();'需要一个具有与绑定相同属性的对象,但在C#中我无法动态创建类。 – FCin