sandy
sandy

Reputation: 736

How to do textwrapping when autogenerate columns is true in DataGrid

I have a DataGrid with autogenerate columns is true because it's columns are getting added dynamically from view model. Still i want to enable the text wrapping because on resizing the columns the text is getting hidden.

XAML Code:

    <DataGrid x:Name="individualGrid" Margin="0,2,0,0" Visibility="{Binding ElementName=individualFilter, Path=IsChecked, Converter={StaticResource BoolToVisibility}}" 
              Grid.Row="4" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" AutoGenerateColumns="True" VerticalScrollBarVisibility="Auto" Height="500"
              ItemsSource="{Binding ElementName=deptFilter, Path=SelectedItem.Individuals.View}" AutomationProperties.AutomationId="AID_UH_individualGrid" ColumnWidth="*" MinColumnWidth="140" />

Please help.

UPDATE 1

I tried the code behind approach by handling auto generating event.It worked but multiple columns of the same type are added.

private void IndividualGrid_OnAutoGeneratingColumn(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;
    if (dg != null) dg.Columns.Add(dgtc);
}

Can someone suggest why the multiple columns are added whereas it should have only two columns.

UPDATE 2

I finally found a solution by handling autogenerating. Here is the solution:

private void IndividualGrid_OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    //Get the existing column
    DataGridTextColumn dgTextC = (DataGridTextColumn)e.Column;

    if (dgTextC != null)
        dgTextC.ElementStyle = individualGrid.Resources["wordWrapStyle"] as Style;
}

But now there is an additional issue.There is an extra column at the start looks like an index column. Any suggestions to this?

Upvotes: 2

Views: 1894

Answers (2)

Davace
Davace

Reputation: 1

Based on your progress, I found success this way:

// Identify the column from its name in the header
if (e.Column.Header.ToString() == "Column To Wrap")
{
    // You can set properties for the column here, personally I
    // chose to set the column's width to a good default.
    e.Column.Width = DataGridLength.SizeToHeader;

    // Cast the column to a DataGridTextColumn
    if (e.Column is DataGridTextColumn textColumn)
    {
        // Create new style based on the existing one.  Adding a Setter to it
        // that turns on word-wrapping.
        var style = new Style(typeof(TextBlock), textColumn.ElementStyle);
        style.Setters.Add(new Setter(TextBlock.TextWrappingProperty, TextWrapping.Wrap));
        textColumn.ElementStyle = style;
    }               
}

Upvotes: 0

Sheridan
Sheridan

Reputation: 69959

The only way to achieve what you want is to handle the AutoGeneratingColumn event. From the DataGrid.AutoGenerateColumns Property page on MSDN:

When the AutoGenerateColumns property is set to true, the AutoGeneratingColumn event will be raised for each column that is created. You can change or cancel the column being created in the AutoGeneratingColumn event handler.

<DataGrid Name="DG1" ItemsSource="{Binding}" AutoGenerateColumns="True" 
    AutoGeneratingColumn="DG1_AutoGeneratingColumn" />

...

//Access and update columns during autogeneration 
private void DG1_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    string headername = e.Column.Header.ToString();

    //Cancel the column you don't want to generate 
    if (headername == "MiddleName")
    {
        e.Cancel = true;
    }

    //update column details when generating 
    if (headername == "FirstName")
    {
        e.Column.Header = "First Name";
    }
    else if (headername == "LastName")
    {
        e.Column.Header = "Last Name";
    }
    else if (headername == "EmailAddress")
    {
        e.Column.Header = "Email";

    }

}

However, you'll basically need to supply a new ItemTemplate for the column to implement text wrapping and you won't be able to do that using this method.

However, there is an additional way of achieving this and that would be for you to override the default Style of the DataGridCell and add a TextBlock that has TextWrapping="Wrap" set on it. Please take a look at the answer to the WPF DataGrid: How do I set columns to TextWrap? question to find out how to do that.

Upvotes: 2

Related Questions