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);
}
An alternate approach is to use a behaviour like this.
You can then drap and drop the behaviour onto the DataGrid in Expression Blend.