Style all DataGridTextColumns via AttachedProperty

眉间皱痕 提交于 2019-12-11 01:39:18

问题


What I tried to do is create a Style to apply a WordWrap on all DataGridTextColumns in a Datagrid without explicitly setting it like this.

<DataGrid ItemsSource="{Binding Lines}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Column1" Binding="{Binding Path=Result1}">
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="{x:Type TextBlock}">
                    <Setter Property="TextWrapping" Value="Wrap"/>
                </Style>
            </DataGridTextColumn.ElementStyle>
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

Unfortunately it is not possible to use some Style as below directly, because DataGridTextColumn isn't a FrameworkElement.

<Style TargetType="{x:Type TextBlock}" x:Key="WrapText">
    <Setter Property="TextWrapping" Value="Wrap"/>
</Style>

I found this workaround https://stackoverflow.com/a/2640862/5381620 by RayBurns and was trying to figure out how it's working. However, I'm new to attached properties and therefore don't understand why it is not working.

The c# code seems to be ok.

public class MyDataGridHelper : DependencyObject
{
    private static readonly DependencyProperty TextColumnStyleProperty = DependencyProperty.RegisterAttached("TextColumnStyle", typeof(Style), typeof(MyDataGridHelper), new PropertyMetadata
    {
        PropertyChangedCallback = (obj, e) =>
        {
            var grid = (DataGrid)obj;
            if (e.OldValue == null && e.NewValue != null)
                grid.Columns.CollectionChanged += (obj2, e2) =>
                {
                    UpdateColumnStyles(grid);
                };
        }
    });

    public static void SetTextColumnStyle(DependencyObject element, Style value)
    {
        element.SetValue(TextColumnStyleProperty, value);
    }
    public static Style GetTextColumnStyle(DependencyObject element)
    {
        return (Style)element.GetValue(TextColumnStyleProperty);
    }

    private static void UpdateColumnStyles(DataGrid grid)
    {
        var style = GetTextColumnStyle(grid);
        foreach (var column in grid.Columns.OfType<DataGridTextColumn>())
            foreach (var setter in style.Setters.OfType<Setter>())
                if (setter.Value is BindingBase)
                    BindingOperations.SetBinding(column, setter.Property, (BindingBase)setter.Value);
                else
                    column.SetValue(setter.Property, setter.Value);
    }
}

I got totally confused is when we get towards figuring out the style setter. Currently I'm trying it this way, which is obviously not working, but actually I don't have a clue what this targettype should really look like.

<local:MyDataGridHelper.TextColumnStyle>
    <Style TargetType="FrameworkElement">
        <Setter Property="TextBlock.TextWrapping" Value="Wrap"/>
    </Style>
</local:MyDataGridHelper.TextColumnStyle>

回答1:


You should set the ElementStyle of the columns to the value of the attached property:

public class MyDataGridHelper : DependencyObject
{
    private static readonly DependencyProperty TextColumnStyleProperty = 
        DependencyProperty.RegisterAttached("TextColumnStyle", typeof(Style), typeof(MyDataGridHelper), new PropertyMetadata
    {
        PropertyChangedCallback = (obj, e) =>
        {
            var grid = (DataGrid)obj;
            if (e.OldValue == null && e.NewValue != null)
                grid.Columns.CollectionChanged += (obj2, e2) =>
                {
                    UpdateColumnStyles(grid);
                };
        }
    });

    public static void SetTextColumnStyle(DependencyObject element, Style value)
    {
        element.SetValue(TextColumnStyleProperty, value);
    }
    public static Style GetTextColumnStyle(DependencyObject element)
    {
        return (Style)element.GetValue(TextColumnStyleProperty);
    }

    private static void UpdateColumnStyles(DataGrid grid)
    {
        var style = GetTextColumnStyle(grid);
        foreach (var column in grid.Columns.OfType<DataGridTextColumn>())
            column.ElementStyle = style;
    }
}

Usage:

<DataGrid>
    <local:MyDataGridHelper.TextColumnStyle>
        <Style TargetType="TextBlock">
            <Setter Property="Foreground" Value="Red"/>
            <Setter Property="TextWrapping" Value="Wrap"/>
        </Style>
    </local:MyDataGridHelper.TextColumnStyle>
    ...
</DataGrid>


来源:https://stackoverflow.com/questions/46690041/style-all-datagridtextcolumns-via-attachedproperty

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!