首页 > 解决方案 > WPF 附加属性的类型被框架破坏

问题描述

考虑一些派生类型的标准附加属性:

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(即使值在 XAML 中被显式设置为)。DerivedKeyBinding

System.InvalidCastException:“无法将“System.Windows.Input.KeyBinding”类型的对象转换为“AttachedPropertyInStyle.DerivedKeyBinding”类型。

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


问题似乎与Name绑定有关 - 如果它是静态值,则代码可以完美执行。

标签: c#wpfxamlattached-properties

解决方案


覆盖Key​Binding.​Create​Instance​Core。从微软文档

继承人注意事项</p>

每个 Freezable 派生类都必须实现此方法。一个典型的实现是简单地调用默认构造函数并返回结果。


public class DerivedKeyBinding : KeyBinding
{
    ...

    protected override Freezable CreateInstanceCore()
    {
        return new DerivedKeyBinding();
    }
}

在 PropertyChangedCallback 你也可以写:

var commandValue = (DerivedKeyBinding)e.NewValue;

推荐阅读