通过附加属性设置所有 DataGridTextColumn 的样式

Style all DataGridTextColumns via AttachedProperty

我尝试做的是创建一个 Style 以在 Datagrid 中的所有 DataGridTextColumns 上应用 WordWrap,而不是像这样明确设置它。

<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>

不幸的是,无法直接使用下面的一些 Style,因为 DataGridTextColumn 不是 FrameworkElement

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

我发现了 RayBurns 的解决方法,并试图弄清楚它是如何工作的。但是,我是附加属性的新手,因此不明白为什么它不起作用。

c#代码好像没问题。

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);
    }
}

当我们着手确定样式时,我完全感到困惑 setter。 目前我正在尝试这种方式,这显然不起作用,但实际上我不知道这个目标类型应该是什么样子。

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

您应该将列的 ElementStyle 设置为附加的值 属性:

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;
    }
}

用法:

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