您无法设置DataGridTextColumn 的样式,因为DataGridTextColumn 不是派生自FrameworkElement(或FrameworkContentElement)。只有 FrameworkElement 等支持样式。
当您尝试在 XAML 中为不是 FrameworkElement 或 FrameworkContentElement 的任何类型创建样式时,您会收到该错误消息。
你如何解决这个问题?与任何问题一样,有志者事竟成。在这种情况下,我认为最简单的解决方案是为 DataGrid 创建一个附加属性以分配 DataGridColumn 样式:
<DataGrid ...>
<local:MyDataGridHelper.TextColumnStyle>
<Style TargetType="FrameworkElement">
... setters here ...
</Style>
</local:MyDataGridHelper.TextColumnStyle>
...
实现将是这样的:
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);
}
}
其工作方式是,每当更改附加属性时,都会为网格上的 Columns.CollectionChanged 事件添加一个处理程序。当 CollectionChanged 事件触发时,所有列都会更新为设置的样式。
请注意,上面的代码没有处理优雅地删除和重新添加样式的情况:注册了两个事件处理程序。对于一个真正强大的解决方案,您可能希望通过添加另一个包含事件处理程序的附加属性来解决此问题,以便可以取消注册事件处理程序,但出于您的目的,我认为这并不重要。
这里的另一个警告是,直接使用 SetBinding 和 SetValue 将导致 DependencyProperty 的 BaseValueSource 为 Local 而不是 DefaultStyle。这可能对您的情况没有影响,但我想我应该提一下。