在动态 DataGrid 中启用 TextWrap
我正在动态生成一个 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;
你能指出我正确的方向吗?
[更新]:解决方案
通过进一步研究,我找到了问题的解决方案。对于自动生成的列,我们需要捕获 AutoGenerateColumn
事件,并用具有 TextBlock< 的
DataGridTemplateColumn
替换默认的 DataGridTextColumn
/代码> 在其中。然后我们可以设置“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);
}
I am generating a DataGrid
dynamically and adding it to a StackPanel
on my WPF application.
As the is dynamically generated, there is no mark up on XAML side for the same and I need to manage the binding and all properties programatically.
I want my DataGrid
to have the values in the cell wrapped to the next line if the text is lengthy. I understand that I need to replace the DataGridCell
with TextBlock
and set the TextWrap
property on it. All the examples that I have found suggest something on those lines itself. However, I couldn't find a way to do it completely from code behind, without XAML.
So far, I have tried to the following code, but it doesn't work.
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;
Can you please point me to the right direction here?
[Update]: Solution
On further researching I was able to get a solution to my issue. For Auto generated columns, we need to capture the AutoGeneratingColumn
event and replace the default DataGridTextColumn
by a DataGridTemplateColumn
which would have a TextBlock
in it. And we can then set the `TextWrappingProperty' to get the text wrapped.
Following is the updated code:
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;
and then the Code under the Event Handler:
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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
另一种方法是使用这样的行为。
然后,您可以将行为拖放到 Expression Blend 中的 DataGrid 上。
An alternate approach is to use a behaviour like this.
You can then drap and drop the behaviour onto the DataGrid in Expression Blend.
我必须说的第一件事是您使用数据网格的方式是错误的。
是一个错误的代码!
WPF
DataGrid
不像其他ItemsControls
那样支持ItemTemplate
属性。您必须在 DataGrid 中提供列模板才能使其正常工作。当
DataGridBoundColumn
\DataGridTextColumn
列提供给DataGrid
时,您可以像这样设置它们的ElementStyle
属性......其中
toolkit
是 .Net 3.5 或更早版本中 WPF 工具包的命名空间。在 .Net 4.0 中,它是标准 System.Windows.Controls 命名空间的一部分。但在您的情况下,完全相同的解决方案有点复杂,因为默认情况下您的网格将
AutoGenerateColumns
设置为 true,自动生成DataGrid.Columns
。因此您没有范围来设置此ElementStyle
属性。因此,我们必须采用 XML 和代码隐藏方法...
XAML:
代码隐藏:
希望这会有所帮助...
注意: 一句话请注意,换行文本块会使 WPF dataGrid 的性能变慢。
First thing I must say is that you are using the datagrid in a wrong manner.
is a wrong code!
WPF
DataGrid
does not entertainItemTemplate
property as otherItemsControls
do. You would have to supply column templates inDataGrid
for it to work correctly.When
DataGridBoundColumn
\DataGridTextColumn
columns are supplied to theDataGrid
, you could set theirElementStyle
property like this...... where
toolkit
is namespace of the WPF toolkit in version .Net 3.5 or prior. In .Net 4.0, its part of the standardSystem.Windows.Controls
namespace.But that exact same solution is a little complicated in your case is because your grid has
AutoGenerateColumns
as true by default that generates theDataGrid.Columns
automatically. So you have no scope to set thisElementStyle
property.So we have to take the XML and code behind approach ...
XAML:
Code Behind:
Hope this helps...
Note: A word of caution that wrapping textblocks make the performance of WPF dataGrid slower.