DependencyProperty默认值和子类化的DataGrid打破属性

DependencyProperty default value and subclassed DataGrid breaks properties
2021-07-22
  •  译文(汉语)
  •  原文(英语)

我在尝试继承wpf的DataGrid控件时遇到了一些奇怪的行为.

假设我有:

class CustomDataGrid<T> : DataGrid { ... }
class FooDataGrid : CustomDataGrid<Foo> { }

和一些xaml:

<local:FooDataGrid ItemsSource="..." SelectionMode="Single" SelectionUnit="FullRow" />

一切正常,我一次只能选择一行.但是,如果我尝试通过执行以下操作更改SelectionMode / SelectionUnit的默认值:

static CustomDataGrid()
{
    DataGrid.SelectionModeProperty.OverrideMetadata( typeof( CustomDataGrid<T> ), new FrameworkPropertyMetadata( DataGridSelectionMode.Single ) );
    DataGrid.SelectionUnitProperty.OverrideMetadata( typeof( CustomDataGrid<T> ), new FrameworkPropertyMetadata( DataGridSelectionUnit.FullRow ) );
}

并将xaml更改为:

<local:FooDataGrid ItemsSource="..." />

它似乎不在乎我的默认值,并且我可以选择多行.现在,奇怪的是,如果我尝试再次在xaml中手动设置属性(同时在静态构造函数中仍具有默认值),我仍然可以选择多行.因此,以某种方式使用那些依赖项属性替代元数据螺钉,导致wpf不在乎xaml中设置的值.

有人知道这里发生了什么吗?

解决过程1

实际的多选行为由CanSelectMultipleItems属性控制,该属性默认为true且仅在SelectionMode属性更改时才更新.覆盖默认值不会调用已更改属性的处理程序,因此CanSelectMultipleItems仍为true.现在,如果您尝试在XAML中设置值,则依赖属性系统将开始对您起作用:默认值为DataGridSelectionMode.Single,并且您将属性设置为相同的值,因此不会再次调用更改属性的处理程序,并且什么也不会发生.

最简单的解决方案-添加一个非静态构造函数并初始化CanSelectMultipleItems属性:

public CustomDataGrid()
{
    CanSelectMultipleItems = SelectionMode != DataGridSelectionMode.Single;
}

另外,您可以为数据网格声明自定义样式,并以样式设置属性值-这样做似乎更"WPF".

速聊1:
啊,那很合情理!是的,我可能应该在样式中使用这些默认值,这很不错.非常感谢!

I've come across some strange behaviour while trying to subclass wpf's DataGrid control.

Let's say I have:

class CustomDataGrid<T> : DataGrid { ... }
class FooDataGrid : CustomDataGrid<Foo> { }

And some xaml:

<local:FooDataGrid ItemsSource="..." SelectionMode="Single" SelectionUnit="FullRow" />

Everything works fine, and I can only select one row at a time. If I however attempt to change the defaults for SelectionMode/SelectionUnit by doing this:

static CustomDataGrid()
{
    DataGrid.SelectionModeProperty.OverrideMetadata( typeof( CustomDataGrid<T> ), new FrameworkPropertyMetadata( DataGridSelectionMode.Single ) );
    DataGrid.SelectionUnitProperty.OverrideMetadata( typeof( CustomDataGrid<T> ), new FrameworkPropertyMetadata( DataGridSelectionUnit.FullRow ) );
}

And change the xaml to:

<local:FooDataGrid ItemsSource="..." />

It does not seem to care about my defaults, and I can select multiple rows. Now, the weird thing is that if I try to set the properties manually in xaml again (while still having the defaults in the static constructor), I can still select multiple rows. So somehow overriding the metadata screws with the workings of those dependency properties, causing wpf to not care about the values set in the xaml.

Does anyone have a clue what is going on here?

Solutions1

Actual multiselect behavior is controlled by CanSelectMultipleItems property, which defaults to true and is only updated when SelectionMode property changes. Overriding default value won't call property changed handler, so CanSelectMultipleItems remains true. Now if you try to set values in XAML, dependency property system starts working against you: default value is DataGridSelectionMode.Single, and you are setting property to the same value, so property changed handler is not called again and nothing happens.

Simpliest solution - add a non-static constructor and initialize CanSelectMultipleItems property:

public CustomDataGrid()
{
    CanSelectMultipleItems = SelectionMode != DataGridSelectionMode.Single;
}

Also you could declare custom style for your datagrid and set property values in style - it seems like a more "WPF-way" to do such things.

Talk1:
Ah, that made perfect sense! And yeah I should probably have those defaults in a style instead, good point. Thanks a lot!
转载于:https://stackoverflow.com/questions/17362034/dependencyproperty-default-value-and-subclassed-datagrid-breaks-properties

本人是.net程序员,因为英语不行,使用工具翻译,希望对有需要的人有所帮助
如果本文质量不好,还请谅解,毕竟这些操作还是比较费时的,英语较好的可以看原文

留言回复
我们只提供高质量资源,素材,源码,坚持 下了就能用 原则,让客户花了钱觉得值
上班时间 : 周一至周五9:00-17:30 期待您的加入