現在、MVVM パターンを使用して Windows ストア アプリを開発しています。ViewModel は、ビューで使用されるいくつかのコマンドを実装します。場合によっては、ビューで複数のコマンドをトリガーしたいことがあります。したがって、ICommand から派生し、監視可能なコマンドのコレクションを保持する CommandGroup クラスを作成しました。XAML を使用してこのコレクションを設定できるようにするために、DependencObject から派生し、ICommand も実装する CommandProxy という別のクラスを作成しました。
アイデアは、ビュー内で次のようなものをサポートすることです:
<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);
}
}
私が間違っていることを教えてくれる人や、なぜこれがうまくいかないのか説明してくれる人はいますか?
敬具
トーマス