【问题标题】:Unable to set CommandBinding inside Datatemplate无法在 Datatemplate 中设置 CommandBinding
【发布时间】:2012-11-19 19:07:32
【问题描述】:

以下是两个 xaml sn-ps,唯一的区别是一个示例直接填充窗口的可视化树和DataContext,而另一个示例通过应用数据模板构造相同的窗口。

可视化树内容/数据上下文

<Window>
    <Window.DataContext>
        <local:MyType />
    </Window.DataContext>

    <DockPanel>
        <DockPanel.CommandBindings>
            <CommandBinding Command="ApplicationCommands.New"
                            CanExecute="OnCanExecuteNew"
                            Executed="OnExecuteNew"
                            />
        </DockPanel.CommandBindings>
        <ToolBarTray DockPanel.Dock="Top">
            <ToolBar>
                <Button Command="ApplicationCommands.New"
                        Content="New"
                        />
            </ToolBar>
        </ToolBarTray>
        <ContentPresenter Content="{Binding SomeProperty}" />
    </DockPanel>
</Window>

业务对象内容和数据模板

<Window>
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:MyType}">
            <DockPanel>
                <DockPanel.CommandBindings>
                    <CommandBinding Command="ApplicationCommands.New"
                                    CanExecute="OnCanExecuteNew"
                                    Executed="OnExecuteNew"
                                    />
                </DockPanel.CommandBindings>
                <ToolBarTray DockPanel.Dock="Top">
                    <ToolBar>
                        <Button Command="ApplicationCommands.New"
                                Content="New"
                                />
                    </ToolBar>
                </ToolBarTray>
                <ContentPresenter Content="{Binding SomeProperty}" />
            </DockPanel>
        </DataTemplate>
    </Window.Resources>
    <Window.Content>
        <local:MyType />
    </Window.Content>
</Window>

第一个示例(可视化树内容和数据上下文)按预期工作,而设计人员在第二个示例中引发编译时错误:“无法绑定到目标方法,因为它的签名或安全透明度是与委托类型的不兼容。”尽管出现设计器错误,但我仍然可以在本地运行应用程序,我已验证路由命令处理程序正在执行。当尝试在其他 PC 上运行应用程序时,应用程序在启动时静默失败,在 Windows 事件日志中留下 xaml 加载错误日志条目。当我从第二个 sn-p 中删除命令绑定时,设计器错误消失了,应用程序在本地和其他 PC 上执行都没有问题。

请有人向我解释异常的原因以及如何在模板中指定命令绑定。

【问题讨论】:

  • 你必须解释“我将 DataContext 从上一个 sn-p 直接移动到窗口的内容中,并将模板的其余部分移动到 DataTemplate 中”
  • 那应该是[...] move the window contents into a DataTemplate and move the DataContext into the window contents。这可能仍然令人困惑,因此我重新构造了问题以更好地说明这两种情况。

标签: c# .net wpf routed-commands


【解决方案1】:

我可以在设计器中重现它并出现以下错误(VS2010 SP1 目标框架 .NET4.0) System.Windows.Markup.XamlParseException: Failed to create a 'CanExecute' from the text 'OnCanExecuteNew'
System.ArgumentException: Error binding to target method.

但我可以构建应用程序,它可以在我的本地机器上运行。
我认为设计师在这里的工作方式与 WPF 运行时不同。 当在设计时应用模板并且 CommandBinding 的事件处理程序得到解析时,生成的模板可视化树仍然不是窗口可视化树的一部分。这就是无法解决处理程序的原因。 作为一种解决方法,我会考虑以下选项。
1)将CommandBindings放在窗口中

<Window.CommandBindings>
    <CommandBinding Command="ApplicationCommands.New"
                    CanExecute="OnCanExecuteNew"
                    Executed="OnExecuteNew"/>
</Window.CommandBindings>

2) 将数据模板的内容包装在 UserControl 中,并将事件处理程序放入它的代码隐藏中。

UserControl.xaml

<UserControl x:Class="WpfApplication1.UserControl1">
    <DockPanel>
        <DockPanel.CommandBindings>
            <CommandBinding Command="ApplicationCommands.New"
                            CanExecute="OnCanExecuteNew"
                            Executed="OnExecuteNew"/>
        </DockPanel.CommandBindings>
        <ToolBarTray DockPanel.Dock="Top">
            <ToolBar>
                <Button Command="ApplicationCommands.New" Content="New"/>
            </ToolBar>
        </ToolBarTray>
        <ContentPresenter Content="{Binding SomeProperty}" />
    </DockPanel>
</UserControl>

Window.xaml

<DataTemplate DataType="{x:Type local:MyType}">
    <local:UserControl1/>
</DataTemplate>

3) 根本不要使用 CommandBindings 并将您的命令对象放在视图模型 (MVVM) 中。

<Button Command="{Binding NewCommand}" Content="New"/>

作为一般规则,我建议避免数据模板和背后代码的紧密耦合。数据模板应该是您获取并放入资源字典的内容。

【讨论】:

  • 数据模板在资源文件中(直到我遇到这里描述的问题)。我也可以将命令绑定放在模板中,因为与命令绑定关联的操作仅限于模板化数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
  • 2016-06-07
  • 1970-01-01
  • 2013-05-29
相关资源
最近更新 更多