I want to create a simple wpf user control which has 2 commands, each with a single CommandParameter which is set by a DependencyProperty in the XAML.
However the value of the property bound to the CommandParameter isn't passed through to the CommandHandler. I'm using ReactiveUI to implement the Commands.
The commands are being called as expected, however the CommandParameter is always 0. So I have 2 questions:
Question 1 Even if I have a single command DependencyProperty called "Command" and a single DependencyProperty parameter called "CommandParameter", the parameter isn't passed through.
Question2 How are Command and CommandParameter properties linked together? Is it a naming convention and if so does it support multiple commands (e.g. is Command1 linked to Command1Parameter?).
I'm aware of passing multiple parameters to a single command, but this is a different scenario where I have 2 separate commands. In this case I actually want to pass the same value to both commands.
I've created a simple test app to demo the problem; The MainWindow.xaml is
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel>
<local:WidgetUserControl x:Name="Widget1" Command="{Binding WidgetCommand1}"
CommandParameter="1" Command2="{Binding WidgetCommand2}" />
<local:WidgetUserControl x:Name="Widget2" Command="{Binding WidgetCommand1}"
CommandParameter="1" Command2="{Binding WidgetCommand2}"/>
</StackPanel>
</Grid>
</Window>
The MainViewModel is:
public class MainViewModel : ReactiveObject
{
public ReactiveCommand<int, Unit> WidgetCommand1 { get; }
public ReactiveCommand<int, Unit> WidgetCommand2 { get; }
public MainViewModel()
{
WidgetCommand1 = ReactiveCommand.Create<int>(ExecuteWidgetCommand1);
WidgetCommand2 = ReactiveCommand.Create<int>(ExecuteWidgetCommand2);
}
private void ExecuteWidgetCommand1(int arg)
{
MessageBox.Show($"Widget Command 1: Parameter {arg}");
}
private void ExecuteWidgetCommand2(int arg)
{
MessageBox.Show($"Widget Command 2: Parameter {arg}");
}
}
The WidgetUserControl XAML is:
<UserControl x:Class="WpfApp1.WidgetUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Border BorderBrush="Aqua" BorderThickness="2">
<StackPanel Orientation="Horizontal" Margin="5">
<Button Content="Button1"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}, Path=Command}"/>
<Button Content="Button2"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}, Path=Command2}"/>
</StackPanel>
</Border>
</Grid>
</UserControl>
The WidgetUserControl code behind looks like this:
public partial class WidgetUserControl : UserControl
{
public WidgetUserControl()
{
InitializeComponent();
}
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(WidgetUserControl));
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(WidgetUserControl),
new PropertyMetadata(OnCommandParameterCallback));
public static readonly DependencyProperty Command2Property = DependencyProperty.Register("Command2", typeof(ICommand), typeof(WidgetUserControl));
public static readonly DependencyProperty Command2ParameterProperty = DependencyProperty.Register("Command2Parameter", typeof(object), typeof(WidgetUserControl),
new PropertyMetadata(OnCommandParameterCallback));
public ICommand Command
{
get => (ICommand)GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
public object CommandParameter
{
get => GetValue(CommandParameterProperty);
set => SetValue(CommandParameterProperty, value);
}
public ICommand Command2
{
get => (ICommand)GetValue(Command2Property);
set => SetValue(Command2Property, value);
}
public object Command2Parameter
{
get => GetValue(Command2ParameterProperty);
set => SetValue(Command2ParameterProperty, value);
}
private static void OnCommandParameterCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// Not sure if this is needed
var control = sender as WidgetUserControl;
control.CommandParameter = e.NewValue;
}
}