2017-02-11 56 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