Запустить команду из кнопки внутри ContentControl?

Я новичок в WPF и пытаюсь динамически добавить кнопку внутри ContentControl, которая должна запускать команду при нажатии. Я использую MVVMLight для обработки команд.

Ниже у меня есть пример с двумя кнопками. Верхняя кнопка помещается непосредственно в StackPanel. Эта кнопка запускает команду, как и ожидалось.

Вторая кнопка размещается внутри ContentControl. Он отображается правильно, но команда не срабатывает при нажатии кнопки. Я предположил, что это связано с тем, что привязка не передается через DataTemplate, но, похоже, это работает, если я использую обычные команды вместо MVVMLight RelayCommands.

Фреймворк удалять не хочу, вот и спрашиваю, может кто знает как исправить? Спасибо

<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>

Вот ViewModel с командой:

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");
        }
    }

person Karmacon    schedule 22.10.2015    source источник
comment
Прокси для привязки может помочь. См. stackoverflow.com/questions/7711275/   -  person dytori    schedule 22.10.2015


Ответы (2)


Проблема здесь в том, что неявный DataContext в ContentTemplate является Content, и для него ничего не установлено. Вам нужно установить Content в некоторую привязку, чтобы соединить DataContext в настоящее время в визуальном дереве, что-то вроде этого:

<ContentControl ContentTemplate="{StaticResource MyButton}" Content="{Binding}"/>
person King King    schedule 22.10.2015
comment
Я бы хотел, чтобы это было так просто, но, к сожалению, это ничего не изменило - person Karmacon; 22.10.2015
comment
@Karmacon то, что я говорю, правильно, если это не работает для вас, возможно, есть еще что-то неправильное который не был показан в вашем вопросе. - person King King; 22.10.2015
comment
Я включил весь свой код в вопрос и попробовал ваше предложение, но ничего не произошло. - person Karmacon; 22.10.2015
comment
@Karmacon только что сам попробовал код, он сработал отлично. Вы хотите, чтобы я выслал демонстрационный проект? - person King King; 22.10.2015
comment
Вы можете открыть проект VS 2012 (требуется как минимум VS 2012)? - person King King; 22.10.2015
comment
Давайте продолжим обсуждение в чате. - person Karmacon; 22.10.2015

Другое решение - дать вашему окну имя:

<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">

Затем привяжите его через его контекст:

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

Это особенно удобно для таких вещей, как ListViews и ItemControls, поскольку их контроллеры домена устанавливаются на элементы списка. Имейте в виду, однако, что это будет работать только для элементов в одном визуальном дереве, если это не так (например, всплывающие меню и т. д.), вам необходимо проксировать привязку как описано в этой статье.

person Mark Feldman    schedule 22.10.2015
comment
Спасибо! Ваше решение отлично работает, и статья дает хорошее объяснение того, что происходит и как это исправить. - person Karmacon; 22.10.2015