2

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

可视化树内容/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 加载错误日志条目。当我从第二个片段中删除命令绑定时,设计器错误消失了,应用程序在本地和其他 PC 上执行都没有问题。

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

4

1 回答 1

2

我可以在设计器中重现以下错误(VS2010 SP1 目标框架 .NET4.0) ,但我可以构建应用程序,它可以在我的本地机器上运行。 我认为设计师在这里的工作方式与 WPF 运行时不同。当在设计时应用模板并且 CommandBinding 的事件处理程序得到解析时,生成的模板可视化树仍然不是窗口可视化树的一部分。这就是处理程序无法解决的原因。作为一种解决方法,我会考虑以下选项。 1)将CommandBindings放在窗口中 System.Windows.Markup.XamlParseException: Failed to create a 'CanExecute' from the text 'OnCanExecuteNew'
System.ArgumentException: Error binding to target method.



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

2) 在 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>

窗口.xaml

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

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

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

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

于 2012-11-21T14:35:00.337 回答