Как обработать событие WPF в MVVM для вложенных элементов управления в окне

ЗАКЛЮЧИТЕЛЬНОЕ ЗАМЕЧАНИЕ Окончательное решение найдено в другом посте

Хотя я оценил предоставленное разъяснение, окончательное решение было фактически предоставлено другим решением, как указано выше. Что бы я ни пытался, привязка через компонент "Имя элемента" не работала. Я должен был пойти на основе "Относительной" иерархии вверх по сетке данных...

<Button Name="btnPrintReport" 
   Command="{Binding DataContext.MyPrintCommand, 
             RelativeSource={RelativeSource FindAncestor, 
                             AncestorType={x:Type DataGrid}}}"
   CommandParameter="{Binding}"
   Height="16" Width="16" HorizontalAlignment="Center" >
   <Image Source="MyButtonImage.png" IsHitTestVisible="True"/>
</Button>

Надеюсь, что-то не слишком сложное в среде WPF / MVVM. Вот сценарий.

У меня есть окно (.xaml) и соответствующая модель представления (.cs). Форма отображается нормально со всеми привязками данных без проблем. (примечание: это НЕ делается через какую-либо коммерческую "платформу")

Одним из элементов управления в окне представления является пользовательский элемент управления сеткой данных со всеми предварительно определенными столбцами, заголовками и содержимым, которые должны отображаться при отображении представления. Все это работает без проблем, даже если элемент управления не "напрямую" определен в файле.xaml главного окна, а просто помещен в форму как сам пользовательский элемент управления (который имеет свой очевидный код.cs).

С "DataContext" главного окна, указывающего на модель представления, и пользовательским элементом управления, который имеет сетку данных

<DataGrid AutoGenerateColumns="False" 
    Name="dataMyStuff"
    ItemsSource="{Binding Path=MyTablePropertyOnViewModel, 
        NotifyOnSourceUpdated=True, 
        NotifyOnTargetUpdated=True}" ... />

Теперь то, что я ищу. В этой сетке данных у меня есть столбец с изображением в первом столбце. Когда я нажимаю на это изображение, я хочу напечатать отчет, относящийся к записи, представленной этой строкой (у нее есть значение PK, которое я использую). Итак, как мне сказать изображению события "KeyUp" перейти в обработчик событий View Model, поскольку именно там находятся данные, и некоторые другие методы, которые мне понадобятся для подготовки вызова к отчету. Часть вида сетки предназначена для косметического отображения пользователю, и, таким образом, нет "функциональных возможностей" непосредственно в этом элементе управления.

- РЕДАКТИРОВАТЬ - за прогресс от ответов

Я настроил свою сетку данных в соответствии с комментариями Джоша и Рэйчел, однако что-то все еще не совсем верно... Увидев, что кнопка использовала экземпляр "Command", я интерпретировал это как необходимость присоединить к экземпляру интерфейсный объект "ICommand" на моей модели представления. Итак, я создал экземпляр. Я знаю, что обработчик команд работает так же, как и для обычных вещей, таких как "Добавить", "Редактировать", "Сохранить", "Отмена", "Выход" и т. Д. Итак, у меня есть новый для этой цели печати. Для простоты он создан как Always Execute, поэтому нет метода для обработки части "CanExecute" элемента управления. Я установил "Команду" для кнопки практически на все итерации, о которых я даже не мог думать, но вот обновление того, что я вижу.

<UserControl>
   <Data grid columns / template, etc to the button>
      <DataTemplate> 
         <Button Name="btnPrintReport" 
            Command="{Binding DataContext.MyPrintCommand}" >
            <Image Source="myPrintImage.png"/>
         </Button>
      </DataTemplate>
   </Data grid columns, etc>
</UserControl>

В моем классе ViewModel (myICommandButtonHandler наследует от ICommand)

private myICommandButtonHandler myPrintCommand;
public myICommandButtonHandler MyPrintCommand
{
   get { if (myPrintCommand == null)
            myPrintCommand = new myICommandButtonHandler(myPrint);
         return myPrintCommand;
       }
}

private void myPrint()
{
   MessageBox.Show( "Doing the print job..." );
}

Теперь, что я вижу. Во время пошаговой инициализации всех элементов управления и тому подобное. Я нажимаю пункт меню, чтобы вызвать мое окно для отображения. Сначала создается экземпляр контроллера View Model. Затем он вызывает Window и передает контроллер View Model в качестве параметра, поэтому он немедленно устанавливается на уровне Window как "DataContext" окна. Затем главное окно переходит к вызову "InitializeComponents" и начинает создавать все остальные встроенные элементы управления, включая этот отдельный класс, содержащий сетку данных, о которой идет речь. В конструкторе этого пользовательского элемента управления (у которого есть сетка данных) еще не установлен "контекст данных", так как остальные элементы управления еще не были инициализированы, и я не знаю, почему / когда "привязки" явно получают " "подключен". Итак, похоже, что попытка сделать привязку к кнопке команды сетки данных не удается. ОДНАКО во время выполнения фактические данные обновляются в сетке, поэтому я знаю, что многое работает.

Таким образом, сетка данных имеет свой "ItemsSource", установленный в свойство свойства "DataView" в модели представления, но привязка "кнопки" не появляется, чтобы увидеть обработчик "MyPrintCommand", который, как я думал, получит нажмите.. и его действие - просто отобразить окно сообщения (пока).

2 ответа

Решение

Обычно я использую поведение AttachedCommand, которое позволяет мне связывать события с командами ViewModel. Например, вы можете использовать

<Image ...
       local:CommandBehavior.Event="KeyUp"  
       local:CommandBehavior.Command="{Binding DataContext.PrintCommand, ElementName=dataMyStuff}"
       local:CommandBehavior.CommandParameter="{Binding }"/>

Я бы порекомендовал использовать событие, отличное от KeyUp, поскольку я не думаю, что изображения могут иметь фокус клавиатуры, поэтому событие KeyUp никогда не будет запущено.

Лучшая альтернатива - использовать кнопку и перезаписать ее шаблоном, чтобы она стала вашим изображением. Это будет поддерживать Click функциональность, и дать вам доступ к Command а также CommandParameter свойства

<Button Command="{Binding DataContext.PrintCommand, ElementName=dataMyStuff}"
        CommandParameter="{Binding }">
    <Button.Template>
        <Image ... />
    </Button.Template>
</Button>

Так же CommandParameter="{Binding }" просто передаст текущий DataRow DataContext (ваш объект данных) в команду

Измените шаблон данных на кнопку с изображением в качестве содержимого. Используйте команду и свойства параметра команды на кнопке для вызова вашего метода печати. Вы можете объявить свою команду печати в своей модели представления и привязать к ней. Ваш параметр может быть выбранной строкой в ​​вашей таблице данных.

Другие вопросы по тегам