2009-06-19 154 views
6

我很难理解RoutedCommand的CommandTarget属性。在XAML中设置命令目标

基本上,我有一些在用户控件(不是窗口)中具有实现的静态命令。我在用户控件中创建一个命令绑定。如果我在usercontrol中声明按钮,那么我可以使用我的路由事件。但是,当该按钮位于usercontrol外部时,我无法使用路由事件。我认为命令目标将解决我的问题。

那么如何设置工具栏usercontrol的按钮的命令目标,以便调用Container的Executed和CanExecuted?

编辑代码与micahtan变化的变化,但我仍然无法得到它CanExecute或执行。

窗口XAML:

<Window x:Class="RoutedCommands.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:RoutedCommands" 
    xmlns:toolbar="clr-namespace:RoutedCommands.Toolbar" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel> 
     <local:Container Width="100" Height="25" x:Name="MyContainer" /> 
     <toolbar:Toolbar Width="100" Height="25" CommandTarget="{Binding MyContainer}" /> 
    </StackPanel> 
</Window> 

工具栏XAML:

<UserControl x:Class="RoutedCommands.Toolbar.Toolbar" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:RoutedCommands" 
    x:Name="MyToolbar" 
    Height="300" Width="300"> 
    <Grid> 
     <Button Command="{x:Static local:Commands.MyCommand}" Content="Try Me" CommandTarget="{Binding ElementName=MyToolbar, Path=CommandTarget, Mode=OneWay}" /> 
    </Grid> 
</UserControl> 

工具栏CS:

public partial class Toolbar : UserControl 
    { 
     public Toolbar() 
     { 
      InitializeComponent(); 
     } 

     // Using a DependencyProperty as the backing store for CommandTarget. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty CommandTargetProperty = 
       DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(Toolbar), new UIPropertyMetadata(null)); 

     public IInputElement CommandTarget 
     { 
      get { return (IInputElement)GetValue(CommandTargetProperty); } 
      set { SetValue(CommandTargetProperty, value); } 
     } 
    } 

集装箱XAML:

<UserControl x:Class="RoutedCommands.Container" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:RoutedCommands" 
    Height="300" Width="300"> 
    <UserControl.CommandBindings> 
     <CommandBinding Command="{x:Static local:Commands.MyCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed" /> 
    </UserControl.CommandBindings> 
    <Grid> 
     <Button Command="{x:Static local:Commands.MyCommand}" Content="Click Me" /> 
    </Grid> 
</UserControl> 

集装箱CS:

public partial class Container : UserControl 
{ 
    public Container() 
    { 
     InitializeComponent(); 
    } 

    private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e) 
    { 
     Console.WriteLine("My Command Executed"); 
    } 

    private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e) 
    { 
     Console.WriteLine("My Command Can Execute"); 
     e.CanExecute = true; 
    } 
} 

RoutedCommands:

namespace RoutedCommands 
{ 
    public static class Commands 
    { 
     public static readonly RoutedUICommand MyCommand = new RoutedUICommand(); 
    } 
} 
+0

我一直没能得到回答我的问题,但我试图与我目前的工作。 – kevindaub 2009-06-20 22:05:01

+0

发布了一些应该让你的场景起作用的代码。 – micahtan 2009-06-22 17:19:58

+0

它并没有真正的帮助。今晚晚些时候我会再尝试一些。 – kevindaub 2009-06-22 22:53:32

回答

7

如果你想使用CommandTargets,我会在你的自定义用户控件,类似于它的上ButtonBase定义方式创建CommandTarget的DependencyProperty。

做完这些之后,将Button的CommandTarget设置为您的自定义UserControl的CommandTarget。

编辑:代码示例

鲁迪的评论是有效的,如果你正在做一个MVVM体系结构 - RelayCommands或包裹代表的一些其他形式在这种情况下正常工作。根据你的代码示例,它看起来并不像你使用这种方法,因此我的原始评论。

至于代码,你只需要改变你的ToolBar类。这假设你的MyCommand类继承自RoutedUICommand。这里的XAML:

<UserControl 
    x:Class="WPFCommandTarget.CustomToolBar" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WPFCommandTarget" 
    x:Name="theControl"> 
    <Grid> 
     <Button 
      x:Name="theButton" 
      Command="{x:Static local:Commands.MyCommand}" 
      CommandTarget="{Binding ElementName=theControl, Path=CommandTarget, Mode=OneWay}" 
      Content="Try Me" /> 
    </Grid> 
</UserControl> 

而这里的代码隐藏:使用System.Windows

; using System.Windows.Controls;

namespace WPFCommandTarget 
{ 
    /// <summary> 
    /// Interaction logic for CustomToolBar.xaml 
    /// </summary> 
    public partial class CustomToolBar : UserControl 
    { 
     public CustomToolBar() 
     { 
      InitializeComponent(); 
     } 

     public IInputElement CommandTarget 
     { 
      get { return (IInputElement)GetValue(CommandTargetProperty); } 
      set { SetValue(CommandTargetProperty, value); } 
     } 

     // Using a DependencyProperty as the backing store for CommandTarget. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty CommandTargetProperty = 
      DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(CustomToolBar), new UIPropertyMetadata(null)); 
    } 
} 

请注意,我在我的测试项目中更改了一些类名/名称空间。你必须改变它们以适应你的需求。

+0

你能提供一个小代码示例或某个方向吗? – kevindaub 2009-06-19 22:15:55

1

您是否曾经勉强使用RelayCommand或DelegateCommand!你可能更适合你需要的东西?

对于使用RelayCommand的例子,读this文章由Josh

布赖恩·诺伊斯也有一个可用的优秀文章here

+0

DelegateCommand?是.Net的一部分还是附加的? – kevindaub 2009-06-19 22:17:44

+0

@rudigrobler - 你确定RelayCommands可以在这种情况下工作吗?他的代码示例将Container和ToolBar作为兄弟之间没有任何参考。 – micahtan 2009-06-19 22:27:32

+0

Relay/DelegateCommands不是框架的一部分...从Josh的文章中获得它或下载Prism! Relay/DelegateCommand根本不依赖Visual树......你给每个命令一个委托来执行,就是这样...... – rudigrobler 2009-06-22 08:10:27