2017-02-11 2 views
0

各列ヘッダーにテキストボックス、コンボボックス、チェックボックスがあり、それらすべてをプロパティにバインドする必要があるように、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> 

編集:私は働いている列を@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.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

あなたが動的に列を追加することができますApp.xamlで

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

:テストするために

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

を(名前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」は、DataGridのItemsSourceを参照していることに注意してください。

+0

これは列の配列に対して機能しますか?私は自分のDataTableにいくつの列があるのか​​分からないからです。私はユーザが 'DataTable'に変換されるcsvファイルを読み込ませるようにしたので、各ファイルのカラム数は異なります。 – FCin

+0

編集された部分を参照してください。 – Ron

+0

私はほとんどそれを動作させましたが、バインディングのために動的に行を追加することはできません。 'dg.Items.Add();'では、バインディングと同じ名前のプロパティを持つオブジェクトが必要ですが、C#では動的にクラスを作成することはできません。 – FCin

関連する問題