C# 如何创建可绑定的命令代理

C# 如何创建可绑定的命令代理,c#,mvvm,windows-8,windows-runtime,windows-store-apps,C#,Mvvm,Windows 8,Windows Runtime,Windows Store Apps,我目前正在使用MVVM模式开发一个Windows应用商店应用程序。ViewModel实现视图使用的两个命令。在某些情况下,我希望视图触发多个命令。因此,我创建了一个CommandGroup类,该类派生自ICommand,并保存一个可观察的命令集合。为了能够使用XAML填充此集合,我创建了另一个名为CommandProxy的类,该类派生自DependencoObject,还实现了ICommand 其想法是在视图中支持类似的内容: <Button Content="Test"> &

我目前正在使用MVVM模式开发一个Windows应用商店应用程序。ViewModel实现视图使用的两个命令。在某些情况下,我希望视图触发多个命令。因此,我创建了一个CommandGroup类,该类派生自ICommand,并保存一个可观察的命令集合。为了能够使用XAML填充此集合,我创建了另一个名为CommandProxy的类,该类派生自DependencoObject,还实现了ICommand

其想法是在视图中支持类似的内容:

<Button Content="Test">
   <Button.Command>
      <vm:CommandGroup>
         <vm:CommandGroup.Commands>
            <vm:CommandProxy Command="{Binding Command1}" CommandParameter="{Binding ElementName=Object1}"/>
            <vm:CommandProxy Command="{Binding Command2}" CommandParameter="{Binding ElementName=Object2}"/>
            <vm:CommandProxy Command="{Binding Command3}" CommandParameter="{Binding ElementName=Object3}"/>
         </vm:CommandGroup.Commands>
      </vm:CommandGroup>
   </Button.Command>
</Button>

在执行语法检查时,一切看起来都很好,但绑定在运行时没有解析。假设ViewModel实现了命令MyCommand,并且视图包含一个名为MyElement的元素,则可以使用以下示例再现此情况:

<Button Content="Test">
   <Button.Command>
      <vm:CommandProxy Command="{Binding MyCommand}" CommandParameter="{Binding ElementName=MyElement}"/>
   </Button.Command>
</Button>

这是CommandProxy类的简化版本,可用于重现问题:

public class CommandProxy : DependencyObject, ICommand
{
    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof(object), typeof(CommandProxy), new PropertyMetadata(null));

    public static readonly DependencyProperty CommandParameterProperty =
        DependencyProperty.Register("CommandParameter", typeof(object), typeof(CommandProxy), new PropertyMetadata(null));

    /// <summary>
    /// Command
    /// </summary>
    public ICommand Command
    {
        get
        {
            return (ICommand)GetValue(CommandProperty);
        }

        set
        {
            SetValue(CommandProperty, value);
        }
    }

    /// <summary>
    /// Command Parameter
    /// </summary>
    public object CommandParameter
    {
        get
        {
            return GetValue(CommandParameterProperty);
        }

        set
        {
            SetValue(CommandParameterProperty, value);
        }
    }

    /// <summary>
    /// Event used to singnal that CanExecute has changed
    /// </summary>
    public event EventHandler CanExecuteChanged;

    /// <summary>
    /// Create new CommandGroupElement
    /// </summary>
    public CommandProxy()
    {
    }

    /// <summary>
    /// Determine whether command can be executed
    /// </summary>
    /// <param name="parameter"></param>
    /// <returns></returns>
    public bool CanExecute(object parameter)
    {
        if (Command != null)
            return Command.CanExecute(CommandParameter);
         return false;
    }

    /// <summary>
    /// Execute Command
    /// </summary>
    /// <param name="parameter">Parameter</param>
    public void Execute(object parameter)
    {
        if (Command != null)
            Command.Execute(CommandParameter);
    }

    /// <summary>
    /// Raise CanExecuteChanged event
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void raiseCanExecuteChanged()
    {
        raiseCanExecuteChanged(this, EventArgs.Empty);
    }

    /// <summary>
    /// Raise CanExecuteChanged event
    /// </summary>
    /// <param name="sender">Parameter</param>
    /// <param name="e"></param>
    protected void raiseCanExecuteChanged(object sender, EventArgs e)
    {
       if (CanExecuteChanged != null)
           CanExecuteChanged(this, EventArgs.Empty);
    }
}
公共类CommandProxy:DependencyObject,ICommand
{
公共静态只读DependencyProperty CommandProperty=
Register(“Command”、typeof(object)、typeof(CommandProxy)、newpropertyMetadata(null));
public static readonly dependencProperty命令参数解释属性=
Register(“CommandParameter”、typeof(object)、typeof(CommandProxy)、newpropertyMetadata(null));
/// 
///命令
/// 
公共ICommand命令
{
得到
{
返回(ICommand)GetValue(CommandProperty);
}
设置
{
SetValue(CommandProperty,value);
}
}
/// 
///命令参数
/// 
公共对象命令参数
{
得到
{
返回GetValue(CommandParameterProperty);
}
设置
{
设置值(CommandParameterProperty,value);
}
}
/// 
///用于标记CanExecute已更改的事件
/// 
公共事件处理程序CanExecuteChanged;
/// 
///创建新CommandGroupElement
/// 
公共命令代理()
{
}
/// 
///确定是否可以执行该命令
/// 
/// 
/// 
公共布尔CanExecute(对象参数)
{
if(命令!=null)
return命令.CanExecute(CommandParameter);
返回false;
}
/// 
///执行命令
/// 
///参数
public void Execute(对象参数)
{
if(命令!=null)
Command.Execute(CommandParameter);
}
/// 
///升起CanExecuteChanged事件
/// 
/// 
/// 
受保护的无效raiseCanExecuteChanged()
{
raiseCanExecuteChanged(此,EventArgs.Empty);
}
/// 
///升起CanExecuteChanged事件
/// 
///参数
/// 
受保护的无效raiseCanExecuteChanged(对象发送方,事件参数e)
{
如果(CanExecuteChanged!=null)
CanExecuteChanged(此为EventArgs.Empty);
}
}
有没有人能告诉我我做错了什么或解释我为什么这样做不起作用

问候


Thomas

在运行时未解决您的意思是输出中存在数据绑定错误?请发布错误您能为您的CommandProxy提供一个用例场景吗?是否有一些原因不只是绑定到调用其他命令的命令?没有绑定错误。DependencyProperties始终包含属性元数据中指定的默认值(在本例中为null,但如果指定另一个默认值,DependencyProperties将包含此值)。看起来根本没有处理数据绑定。其背后的思想是分离视图和viewnodel,这样viewmodel就不需要知道任何有关视图的信息。在某些情况下,例如按钮可能必须保存数据并关闭弹出窗口或触发导航。当然,这可以通过使用特定于视图的命令或codebehind来解决,但是为了真正分离视图和编码,我希望我的viewmodelbase公开一组服务命令,这些命令可以被视图用于操作元素和导航,并且可以被XAML和数据绑定访问。因此,在viewmodel中不需要view spec.命令。