Search code examples
c#wpfmvvmuser-controlsicommand

WPF C# Commands bound to userControl won't fire


So, I have created a UserControl which really is an "advanced button". I have implemented Dependency Properties, one of which is ICommand, that is supposed to be bindable further when control is used in an actual Window.

However, for some reason the Command doesn't work.

When I tried an exact same approach on a regular button, everything worked fine (thus it's not the fault of my DelegateCommand implementation or my ViewModel).

I tried to followup on why the bound command doesn't fire, but I couldn't find a reliable reason for it not to.

Here is my UserControl XAML:

<Window x:Class="NoContact.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:NoContact"
    mc:Ignorable="d"
    xmlns:userControls="clr-namespace:NoContact.UserControls"
    Title="MainWindow" Height="800" Width="960" Background="#22282a">
<Border BorderThickness="1" BorderBrush="#ffcd22" Margin="10,10,10,10">
<Grid>
    <Button HorizontalContentAlignment="Stretch" Foreground="{Binding ElementName=ImageButtonUC, Path=Foreground}"
            Background="{Binding ElementName=ImageButtonUC, Path=Background}">
        <DockPanel Width="{Binding ElementName=ImageButtonUC, Path=ActualWidth}">
            <Image Source="{Binding ElementName=ImageButtonUC, Path=Image}" DockPanel.Dock="Left"
                   Height="{Binding ElementName=ImageButtonUC, Path=ActualHeight, Converter={StaticResource HeightConverter}}" 
                   Width="{Binding ElementName=ImageButtonUC, Path=ActualWidth, Converter={StaticResource HeightConverter}}" VerticalAlignment="Center"/>
            <TextBlock Text="{Binding ElementName=ImageButtonUC, Path=Text}" FontSize="17" VerticalAlignment="Center" />
        </DockPanel>
    </Button>
</Grid>
<UserControl.Resources>
    <Style TargetType="{x:Type Button}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border Background="{TemplateBinding Background}">
                        <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>

And here is my UserControl code-behind:

public partial class ImageButton : UserControl
{

    // OTHER IRRELEVANT CLASS PARAMETERS ARE HERE

    public ICommand ClickCommand
    {
        get { return (ICommand)GetValue(ClickCommandProperty); }
        set { SetValue(ClickCommandProperty, value); }
    }

    // OTHER IRRELEVANT DEPENDENCY PROPERTIES ARE HERE

    public static DependencyProperty ClickCommandProperty =
        DependencyProperty.Register("ClickCommand", typeof(ICommand), typeof(ImageButton));

    public ImageButton()
    {
        InitializeComponent();
    }
}

Finally, this is how I use my control:

 <userControls:ImageButton x:Name="phoneButton" ClickCommand="{Binding Path=MyButtonClickCommand}" Style="{StaticResource phoneImageButtonUCStyle}" Text="Telefon" Width="200" Height="100" VerticalAlignment="Top" />

The DataContext of the control is set on a stackpanel, that is wrapped around my control. I have also tried setting it directly on the control, no effect.

Again, doing the same on a regular button works just fine.


Solution

  • I have finally solved the problem - and it was pretty trivial.

    I had ommited the most important binding - UserControl's button Command to UserControl's Dependency property.

    Changing it like this made it work:

    <Button HorizontalContentAlignment="Stretch" Foreground="{Binding ElementName=ImageButtonUC, Path=Foreground}"
            Background="{Binding ElementName=ImageButtonUC, Path=Background}"
            Command="{Binding ElementName=ImageButtonUC, Path=ClickCommand}">