【问题标题】:trainings DependencyObject - custom command培训 DependencyObject - 自定义命令
【发布时间】:2017-10-08 04:05:01
【问题描述】:

我尝试创建从 DependencyObject 和 ICommand 继承的 Command。我有以下代码:

    public class CustomCommand : DependencyObject, ICommand
{
    public static readonly DependencyProperty CommandProperty;
    public static readonly DependencyProperty AfterCommandProperty;
    static CustomCommand()
    {
        var ownerType = typeof(CustomCommand);
        CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(Action), ownerType, new PropertyMetadata(null));
        AfterCommandProperty = DependencyProperty.RegisterAttached("AfterCommand", typeof(Action), ownerType, new PropertyMetadata(null));
    }

    public Action Command
    {
        get => (Action)GetValue(CommandProperty);
        set => SetValue(CommandProperty, value);
    }

    public Action AfterCommand
    {
        get => (Action)GetValue(CommandProperty);
        set => SetValue(CommandProperty, value);
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        // Command & AfterCommand are always null
    }
}

    <Button Content="Test">
    <Button.Command>
        <command:CustomCommand  Command="{Binding Copy}" AfterCommand="{Binding AfterCopy}" />
    </Button.Command>
</Button>

当我按下测试按钮时 CommandAfterCommand 为空。你有想法吗 ?什么是最好的方法,因为我无法将 ICommand 引用添加到我的 ViewModel。

谢谢

【问题讨论】:

  • 更改为:Command="{Binding Copy, PresentationTraceSources.TraceLevel=High}" 并查看您在调试输出中看到的内容。我怀疑您会发现没有上下文,因为它不在可视化树中。您可以尝试将命令创建为资源,和/或您可以尝试各种绑定代理策略。
  • 顺便说一下,AfterCommand 属性中有一个错误:它将 CommandProperty 传递给 GetValue/SetValue,而不是 AfterCommandProperty

标签: wpf dependency-properties dependencyobject


【解决方案1】:

您的 CustomCommand 实例不在可视化树中,因此绑定是个问题。没有办法获得 DataContext。尝试在绑定上添加跟踪:

<Button.Command>
    <local:CustomCommand
        Command="{Binding TestAction, PresentationTraceSources.TraceLevel=High}"
        />
</Button.Command>

“未找到框架导师”是您将在调试输出中看到的错误。 “你不能从这里到那里”是他们怎么说的下东区。 XAML 中的上下文是父对父的问题,但从这里重要的意义上说,这件事没有父。

但这很容易解决。使用绑定代理。这是我从various questions and answers on Stack Overflow 偷了几次的城市自行车实现:

public class BindingProxy : Freezable
{
    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}

将实例定义为某个包含范围内的资源,该范围具有所需的Action 属性所在的DataContext。没有路径的{Binding} 只返回DataContext,在下面的例子中,这将是窗口的视图模型。

<Window.Resources>
    <local:BindingProxy
        x:Key="MainViewModelBindingProxy"
        Data="{Binding}"
        />
</Window.Resources>

并像这样使用它。 BindingProxyData 属性绑定到视图模型,因此使用 Data.WhateverPropertyYouWant 的路径。我打电话给我的Action 属性TestAction

<Button
    Content="Custom Command Test"
    >
    <Button.Command>
        <local:CustomCommand
            Command="{Binding Data.TestAction, Source={StaticResource MainViewModelBindingProxy}}"
            />
    </Button.Command>
</Button>

注意

您的AfterCommand 属性中还有一个错误:它将CommandProperty 传递给GetValue/SetValue,而不是AfterCommandProperty

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 2012-06-15
    相关资源
    最近更新 更多