2012-02-10 4 views
2

DataGridを動的に生成し、それをWPFアプリケーションのStackPanelに追加しています。ダイナミックDataGridでTextWrapを有効にする

動的に生成されるので、同じものに対してXAML側にマークアップはなく、プログラムですべてのプロパティとバインディングを管理する必要があります。

私のDataGridは、テキストが長い場合、次の行に折り返されたセルの値を持つことを望みます。 DataGridCellTextBlockに置き換え、TextWrapプロパティを設定する必要があることを理解しています。私が見つけたすべての例は、それらの行自体に何かを示唆しています。しかし、私はXAMLを使わずにコードの背後から完全にそれを行う方法を見つけることができませんでした。

これまでのところ、次のコードを試しましたが、動作しません。

DataGrid dg = new DataGrid(); 

dg.ItemsSource = ((DataSet)data).Tables[0].DefaultView; 
dg.DataContext = ((DataSet)data).Tables[0].DefaultView; 

DataTemplate ct = new DataTemplate(typeof(DataGridCell)); 
FrameworkElementFactory tb = new FrameworkElementFactory(typeof(TextBlock)); 
tb.SetValue(TextBlock.TextWrappingProperty, TextWrapping.Wrap); 
ct.VisualTree = tb; 

dg.ItemTemplate = ct; 
dg.ColumnWidth = 300; 

ここに正しい方向を教えていただけますか?

[更新]:ソリューション

さらに再探索で私は私の問題の解決策を得ることができました。自動生成された列の場合は、AutoGeneratingColumnイベントをキャプチャし、デフォルトのDataGridTextColumnDataGridTemplateColumnで置き換えます。TextBlockになります。次に、テキストをラップするために `TextWrappingProperty 'を設定することができます。

後は更新されたコードです:

DataGrid dg = new DataGrid(); 

dg.ItemsSource = ((DataSet)data).Tables[0].DefaultView; 
dg.DataContext = ((DataSet)data).Tables[0].DefaultView; 

DataTemplate ct = new DataTemplate(typeof(DataGridCell)); 
FrameworkElementFactory tb = new FrameworkElementFactory(typeof(TextBlock)); 
tb.SetValue(TextBlock.TextWrappingProperty, TextWrapping.Wrap); 
ct.VisualTree = tb; 

dg.AutoGeneratingColumn += new EventHandler<DataGridAutoGeneratingColumnEventArgs>(dg_AutoGeneratingColumn); 

dg.MaxColumnWidth = 300; 

[イベントハンドラの下のコード:私は言わなければならない

private void dg_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) 
     { 
     //cancel the auto generated column 
     e.Cancel = true; 

     //Get the existing column 
     DataGridTextColumn dgTextC = (DataGridTextColumn)e.Column; 

     //Create a new template column 
     DataGridTemplateColumn dgtc = new DataGridTemplateColumn(); 

     DataTemplate dataTemplate = new DataTemplate(typeof(DataGridCell)); 

     FrameworkElementFactory tb = new FrameworkElementFactory(typeof(TextBlock)); 
     tb.SetValue(TextBlock.TextWrappingProperty, TextWrapping.Wrap); 
     dataTemplate.VisualTree = tb; 

     dgtc.Header = dgTextC.Header; 
     dgtc.CellTemplate = dataTemplate; 

     tb.SetBinding(TextBlock.TextProperty, dgTextC.Binding); 

     //add column back to data grid 
     DataGrid dg = sender as DataGrid; 
     dg.Columns.Add(dgtc); 
    } 
+0

さらなる調査で、私は 'AutoGeneratingColumn'イベントをキャプチャし、そこに' DataTemplate'を適用する必要があることを発見しました。私はその作業を進めていますが、新しい列型にバインドされた値を取得するのには時間がかかります。 –

答えて

4

代わりの方法は、このような動作を使用することです。

public class DataGridWrapTextBehaviour : Behavior<DataGrid> 
    { 
    private DataGrid DataGrid 
    { 
     get { return AssociatedObject as DataGrid; } 
    } 

    private Style ElementStyle { get; set; } 
    private Style EditingElementStyle { get; set; } 

    protected override void OnAttached() 
    { 
     base.OnAttached(); 

     this.ElementStyle = new Style(typeof(TextBlock)); 
     this.ElementStyle.Setters.Add(new Setter(TextBlock.TextWrappingProperty, TextWrapping.Wrap)); 

     this.EditingElementStyle = new Style(typeof(TextBox)); 
     this.EditingElementStyle.Setters.Add(new Setter(TextBox.TextWrappingProperty, TextWrapping.Wrap)); 

     this.DataGrid.Columns.CollectionChanged += Columns_CollectionChanged; 
    } 

    protected override void OnDetaching() 
    { 
     this.DataGrid.Columns.CollectionChanged -= Columns_CollectionChanged; 
     base.OnDetaching(); 
    } 

    private void Columns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     foreach (var column in this.DataGrid.Columns.OfType<DataGridTextColumn>()) 
     { 
      column.ElementStyle = this.ElementStyle; 
      column.EditingElementStyle = this.EditingElementStyle; 
     } 
    } 
    } 

Expression Blendのデータグリッドに動作をドラップ&ドロップできます。

0

最初のものは、あなたが間違った方法でデータグリッドを使用していることです。

dg.ItemTemplate = ct; 

は間違ったコードです!

WPF DataGridがありませんItemTemplateプロパティは他と同じItemsControlsです。正しく動作させるには、列テンプレートをDataGridに指定する必要があります。 toolkitバージョンでWPFツールキットの名前空間.NET 3.5以上である

DataGridBoundColumnDataGridTextColumn \列がDataGridに供給されている場合、あなたはこのような彼らのElementStyleプロパティを設定することができ...

 <toolkit:DataGrid 
       AutoGenerateColumns="False">     
      <toolkit:DataGrid.Columns> 
       <toolkit:DataGridTextColumn 
         Binding="{Binding SomeProperty}"> 
        <toolkit:DataGridTextColumn.ElementStyle> 
         <Style TargetType="{x:Type TextBlock}"> 
          <Setter Property="TextWrapping" 
            Value="Wrap"/> 
         </Style> 
        </toolkit:DataGridTextColumn.ElementStyle> 
       </toolkit:DataGridTextColumn> 
      </toolkit:DataGrid.Columns> 
     </toolkit:DataGrid>  

...事前に。 .Net 4.0では、標準のSystem.Windows.Controls名前空間の一部です。

グリッドがAutoGenerateColumnsをデフォルトでtrueに設定して自動的にDataGrid.Columnsを生成するため、まったく同じ解決策が少し複雑です。したがって、このElementStyleプロパティを設定する範囲がありません。

私たちはアプローチの背後にあるXMLとコードを取らなければなりません...

XAML:

 <toolkit:DataGrid x:Name="dg"> 
      <toolkit:DataGrid.Resources> 
       <Style TargetType="{x:Type TextBlock}" 
         x:Key="WrappedTextBlockStyle"> 
        <Setter Property="TextWrapping" Value="Wrap"/> 
       </Style> 
      </toolkit:DataGrid.Resources>     
     </toolkit:DataGrid> 

コードの後ろ:このことができます

dg.ItemsSource = ((DataSet)data).Table[0].DefaultView; 
    dg.Columns.CollectionChanged 
     += new NotifyCollectionChangedEventHandler(
       Columns_CollectionChanged); 

    void Columns_CollectionChanged(
     object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.NewItems.Count > 0) 
     { 
      foreach(DataGridColumn col in e.NewItems) 
      { 
       if (col is DataGridTextColumn) 
       { 
        ((DataGridTextColumn) col).ElementStyle 
         = dg.Resources["WrappedTextBlockStyle"] as Style; 
       } 
      } 
     } 
    } 

希望...

注:はラップテキストブロックは、注意の言葉を作ることWPF dataGridのパフォーマンスが低下します。

+0

ええ、あなたは正しいです、私は、 'ItemTemplate'を使用して正しい方法ではない、図を行った。しかし、私はあなたのアプローチを使用することはできません。なぜなら、このためにXAMLマークアップに何もないからです。実行時に 'StackPanel'に追加される、動的に生成されるコントロールです。 –

+0

なぜこれをコードdebhindで使用できないのですか? 'WrappedTextBlockStyle'のようなスタイルは、コード内で動的に作成することもできます。サンプルを検索する –

+0

あなたの助けを借りて@AngelWPF、私はすでに別のアプローチの真っ只中にあったと働いた。しかし、私はいつかあなたのアプローチを試みるでしょう。 :) –

関連する問題