为什么我不能设置DataGridTextColumn的样式?

Nik*_*ike 34 wpf datagrid styles

我尝试DataGridTextColumn使用以下代码创建样式

<Style TargetType="{x:Type DataGridTextColumn}">
           ...
</Style>
Run Code Online (Sandbox Code Playgroud)

但是,Visual Studio 2010 {x:Type DataGridTextColumn}以蓝线突出显示并详细说明:Exception has been thrown by the target of an invocation.

为什么会发生这种情况,我该如何解决?

Ray*_*rns 25

你不能设置样式DataGridTextColumn因为DataGridTextColumn不是从FrameworkElement(或FrameworkContentElement)派生的.只有FrameworkElement等支持样式.

当您尝试在XAML中为任何非类型的类型创建样式时,FrameworkElement或者FrameworkContentElement您收到该错误消息.

你是如何解决这个问题的?与任何问题一样,只要有遗嘱就有办法.在这种情况下,我认为最简单的解决方案是为DataGrid创建一个附加属性来分配DataGridColumn样式:

<DataGrid ...>
  <local:MyDataGridHelper.TextColumnStyle>
    <Style TargetType="FrameworkElement">
      ... setters here ...
    </Style>
  </local:MyDataGridHelper.TextColumnStyle>
  ...
Run Code Online (Sandbox Code Playgroud)

实施将是这样的:

public class MyDataGridHelper : DependencyObject
{
  // Use propa snipped to create attached TextColumnStyle with metadata:
  ... 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);
        }
    }
  }
  private void UpdateStyles(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, setter.Value);
        else
          column.SetValue(setter.Property, setter.Value);
  }
}
Run Code Online (Sandbox Code Playgroud)

这种方式的工作方式是,每次更改附加属性时,都会为网格上的Columns.CollectionChanged事件添加一个处理程序.触发CollectionChanged事件时,将使用设置的样式更新所有列.

请注意,上面的代码不能处理删除样式并正常重新添加样式的情况:注册了两个事件处理程序.对于一个非常强大的解决方案,您可能希望通过添加包含事件处理程序的另一个附加属性来解决此问题,以便可以取消注册事件处理程序,但出于您的目的,我认为这并不重要.

另一个需要注意的是,直接使用SetBinding和SetValue将导致DependencyProperty具有BaseValueSource Local而不是DefaultStyle.这可能会对你的情况没有影响,但我想我应该提一下.


Pat*_*ham 5

样式标签必须在正确的位置.您的数据网格现在看起来像这样:

    <DataGrid>
        <DataGrid.Columns>
            <DataGridTextColumn />
        </DataGrid.Columns>
    </DataGrid>
Run Code Online (Sandbox Code Playgroud)

您可能最初尝试直接在DataGridTextColumn元素中添加样式标记,这将无法正常工作.但是,您可以在"DataGridTextColumn"元素中为"DataGridTextColumn.ElementStyle"和/或"DataGridTextColumn.EditingElementStyle"创建元素.然后,每个元素标记中都可以包含样式标记:

    <DataGrid>
        <DataGrid.Columns>
            <DataGridTextColumn>
                <DataGridTextColumn.ElementStyle>
                    <Style TargetType="TextBlock">
                        <Setter Property="Background" Value="Green"></Setter>
                    </Style>
                </DataGridTextColumn.ElementStyle>
                <DataGridTextColumn.EditingElementStyle>
                    <Style TargetType="TextBox">
                        <Setter Property="Background" Value="Orange"></Setter>
                    </Style>
                </DataGridTextColumn.EditingElementStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
Run Code Online (Sandbox Code Playgroud)

一个样式将应用于查看,另一个样式将在单元格处于编辑模式时应用.请注意,在编辑时,它会在查看时从TextBlock更改为TextBox(这首先得到了我!).