Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fire a command from a Button inside a ContentControl?

I'm new to WPF and I'm trying to dynamically add a Button inside a ContentControl, which should fire a command when clicked. I'm using MVVMLight to handle the Commands.

Below I have an example with two buttons. The top button is placed directly into the StackPanel. This button fires off the Command as expected.

The second button is placed inside a ContentControl. It displays correctly, but the Command does not fire when the button is clicked. I assumed this is because the Binding does not transfer down through the DataTemplate, but it seems to work if I use regular Commands instead of MVVMLight RelayCommands.

I don't want to remove the framework, so I'm wondering if anyone knows how to fix it? Thanks

<Window x:Class="ContentControlExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:ContentControlExample.ViewModel">

    <Window.DataContext>
        <vm:MainViewModel />
    </Window.DataContext>

    <Window.Resources>
        <DataTemplate x:Key="MyButton" >
            <Button Content="SUBMIT" Command="{Binding MyCommand}" Width="200" Height="50"/>
        </DataTemplate>
    </Window.Resources>

    <StackPanel>

        <!--When this button is clicked, the Command executes as expected-->
        <Button Content="SUBMIT" Command="{Binding MyCommand}" Width="200" Height="50"/>


        <!--Nothing happens when this button is clicked-->
        <ContentControl ContentTemplate="{StaticResource MyButton}"/>
    </StackPanel>
</Window>

Here's the ViewModel with the command:

public class MainViewModel : ViewModelBase
{
        public ICommand MyCommand { get; private set; }

        public MainViewModel()
        {
            MyCommand = new RelayCommand(MyCommand_Executed, MyCommand_CanExecute);
        }

        private bool MyCommand_CanExecute()
        {
            return true;
        }

        private void MyCommand_Executed()
        {
            MessageBox.Show("The command executed");
        }
    }
like image 662
Karmacon Avatar asked Sep 03 '26 15:09

Karmacon


2 Answers

The problem here is the implicit DataContext in ContentTemplate is the Content and this has not been set to anything. You need to set Content to some Binding to bridge the DataContext currently in the visual tree, something like this:

<ContentControl ContentTemplate="{StaticResource MyButton}" Content="{Binding}"/>
like image 89
King King Avatar answered Sep 05 '26 04:09

King King


Another solution is to give your Window a name:

<Window x:Class="ContentControlExample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:ContentControlExample.ViewModel"
    x:Name="_this">

Then bind via its context instead:

<Button Content="SUBMIT" Command="{Binding ElementName=_this, Path=DataContext.MyCommand}" Width="200" Height="50"/>

This is particularly handy for things like ListViews and ItemControls, as their DCs get set to the list elements. Keep in mind though that this will only work on members within the same visual tree, if that's not the case (e.g. popup menus etc) then you need to proxy a binding as described in this article.

like image 38
Mark Feldman Avatar answered Sep 05 '26 04:09

Mark Feldman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!