Как обработать событие 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 (ваш объект данных) в команду
Измените шаблон данных на кнопку с изображением в качестве содержимого. Используйте команду и свойства параметра команды на кнопке для вызова вашего метода печати. Вы можете объявить свою команду печати в своей модели представления и привязать к ней. Ваш параметр может быть выбранной строкой в вашей таблице данных.