我正在动态生成DataGrid
并将其添加到我的WPF应用程序上的StackPanel
。
由于它是动态生成的,因此XAML方面没有标记,我需要以编程方式管理绑定和所有属性。
如果文本很长,我希望我的DataGrid
将单元格中的值包装到下一行。我了解我需要将DataGridCell
替换为TextBlock
并在其上设置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
事件,并将DataGridTextColumn
替换为DataGridTemplateColumn
,其中包含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 :(得分: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中的DataGrid上。
答案 1 :(得分:0)
我必须说的第一件事是你以错误的方式使用数据网格。
dg.ItemTemplate = ct;
是错误的代码!
WPF DataGrid
不像其他ItemTemplate
那样接受ItemsControls
属性。您必须在DataGrid
中提供列模板才能正常工作。
当DataGridBoundColumn
DataGridTextColumn
列提供给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>
...其中toolkit
是.Net 3.5或更早版本中WPF工具包的命名空间。在.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的性能变慢。