WPF 附加 属性 的类型被框架破坏
WPF Attached Property's Type is being mangled by framework
考虑一些派生类型的几乎标准附件属性:
public class DerivedKeyBinding : KeyBinding
{
public string Name; //shortened, make this propdp
}
public class KeyBindingExtenstions
{
public static DerivedKeyBinding GetCommand(DependencyObject obj) {
return (DerivedKeyBinding)obj.GetValue(CommandProperty);
}
public static void SetCommand(DependencyObject obj, DerivedKeyBinding value) {
obj.SetValue(CommandProperty, value);
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof(DerivedKeyBinding), typeof(KeyBindingExtenstions), new UIPropertyMetadata(null, CommandChanged));
private static void CommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var commandValue = GetCommand(d);
}
}
稍后在XAML中设置:
<Grid>
<Grid.Style>
<Style>
<Setter Property="local:KeyBindingExtenstions.Command">
<Setter.Value>
<local:DerivedKeyBinding Name="{Binding Title, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
</Setter.Value>
</Setter>
</Style>
</Grid.Style>
</Grid>
然而,这将在 var commandValue = GetCommand(d);
行崩溃,因为 local:DerivedKeyBinding
丢失到 KeyBinding
过程中的某个地方。
由于某些奇怪的原因,DerivedKeyBinding
类型的 属性 被设置为 KeyBinding
类型的值(即使值 显式 设置为 DerivedKeyBinding
在 XAML).
System.InvalidCastException: 'Unable to cast object of type 'System.Windows.Input.KeyBinding' to type 'AttachedPropertyInStyle.DerivedKeyBinding'.'
为什么会发生这种情况,我该如何解决这个问题?
问题似乎与 Name
绑定有关 - 如果它是静态值,代码将完美执行。
覆盖 KeyBinding.CreateInstanceCore
. From Microsoft Docs:
Notes to Inheritors
Every Freezable derived class must implement this method. A typical implementation is to simply call the default constructor and return the result.
public class DerivedKeyBinding : KeyBinding
{
...
protected override Freezable CreateInstanceCore()
{
return new DerivedKeyBinding();
}
}
在 PropertyChangedCallback 中你也可以这样写:
var commandValue = (DerivedKeyBinding)e.NewValue;
考虑一些派生类型的几乎标准附件属性:
public class DerivedKeyBinding : KeyBinding
{
public string Name; //shortened, make this propdp
}
public class KeyBindingExtenstions
{
public static DerivedKeyBinding GetCommand(DependencyObject obj) {
return (DerivedKeyBinding)obj.GetValue(CommandProperty);
}
public static void SetCommand(DependencyObject obj, DerivedKeyBinding value) {
obj.SetValue(CommandProperty, value);
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof(DerivedKeyBinding), typeof(KeyBindingExtenstions), new UIPropertyMetadata(null, CommandChanged));
private static void CommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var commandValue = GetCommand(d);
}
}
稍后在XAML中设置:
<Grid>
<Grid.Style>
<Style>
<Setter Property="local:KeyBindingExtenstions.Command">
<Setter.Value>
<local:DerivedKeyBinding Name="{Binding Title, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
</Setter.Value>
</Setter>
</Style>
</Grid.Style>
</Grid>
然而,这将在 var commandValue = GetCommand(d);
行崩溃,因为 local:DerivedKeyBinding
丢失到 KeyBinding
过程中的某个地方。
由于某些奇怪的原因,DerivedKeyBinding
类型的 属性 被设置为 KeyBinding
类型的值(即使值 显式 设置为 DerivedKeyBinding
在 XAML).
System.InvalidCastException: 'Unable to cast object of type 'System.Windows.Input.KeyBinding' to type 'AttachedPropertyInStyle.DerivedKeyBinding'.'
为什么会发生这种情况,我该如何解决这个问题?
问题似乎与 Name
绑定有关 - 如果它是静态值,代码将完美执行。
覆盖 KeyBinding.CreateInstanceCore
. From Microsoft Docs:
Notes to Inheritors
Every Freezable derived class must implement this method. A typical implementation is to simply call the default constructor and return the result.
public class DerivedKeyBinding : KeyBinding
{
...
protected override Freezable CreateInstanceCore()
{
return new DerivedKeyBinding();
}
}
在 PropertyChangedCallback 中你也可以这样写:
var commandValue = (DerivedKeyBinding)e.NewValue;