为什么我不能设置 DataGridTextColumn 的样式? [英] Why can't I style a DataGridTextColumn?
问题描述
我尝试使用以下代码为 DataGridTextColumn
创建样式
I tried to create a Style for DataGridTextColumn
with the following code
<Style TargetType="{x:Type DataGridTextColumn}">
...
</Style>
但是,Visual Studio 2010 用蓝线突出显示 {x:Type DataGridTextColumn}
并详细说明:调用目标已抛出异常.
However, Visual Studio 2010 highlights {x:Type DataGridTextColumn}
with a blue line and elaborates: Exception has been thrown by the target of an invocation.
为什么会发生这种情况,我该如何解决?
Why does this happen and how do I fix it?
推荐答案
您不能设置 DataGridTextColumn
的样式,因为 DataGridTextColumn
不是从 FrameworkElement派生的代码>(或
FrameworkContentElement
).只有 FrameworkElement 等支持样式.
You can't style the DataGridTextColumn
because DataGridTextColumn
does not derive from FrameworkElement
(or FrameworkContentElement
). Only FrameworkElement, etc supports styling.
当您尝试在 XAML 中为不是 FrameworkElement
或 FrameworkContentElement
的任何类型创建样式时,您会收到该错误消息.
When you attempt to create a style in XAML for any type that is not a FrameworkElement
or FrameworkContentElement
you get that error message.
你是如何解决这个问题的?与任何问题一样,有志者事竟成.在这种情况下,我认为最简单的解决方案是为 DataGrid 创建附加属性以分配 DataGridColumn 样式:
How do you solve this? As with any problem, where there is a will there is a way. In this case I think the easiest solution is to create an attached property for DataGrid to assign a DataGridColumn style:
<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 事件触发时,所有列都将更新为设置的样式.
The way this works is, any time the attached property is changed, a handler is added for the Columns.CollectionChanged event on the grid. When the CollectionChanged event fires, all columns are updated with the style that was set.
请注意,上面的代码没有处理优雅地移除和重新添加样式的情况:注册了两个事件处理程序.对于真正强大的解决方案,您可能希望通过添加另一个包含事件处理程序的附加属性来解决此问题,以便可以取消注册事件处理程序,但对于您的目的,我认为这并不重要.
Note that the above code does not handle the situation where a style is removed and re-added gracefully: Two event handlers are registered. For a really robust solution you would want to fix this by adding another attached property containing the event handler so the event handler could be unregistered, but for your purpose I think this is unimportant.
这里的另一个警告是,直接使用 SetBinding 和 SetValue 将导致 DependencyProperty 的 BaseValueSource 为 Local
而不是 DefaultStyle
.这可能对你的情况没有影响,但我想我应该提到它.
Another caveat here is that the direct use of SetBinding and SetValue will cause the DependencyProperty to have a BaseValueSource of Local
instead of DefaultStyle
. This will probably make no difference in your case but I thought I should mention it.
这篇关于为什么我不能设置 DataGridTextColumn 的样式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!