Команды и меню
У меня есть UserControl, который я построил, который содержит несколько границ, которые содержат элементы управления TextBlock. Свойство Text для TextBlocks установлено на данные из моего объекта ViewModel.
Я добавил пару контекстных меню к ресурсам UserControl:
<UserControl.Resources>
<ContextMenu x:Key="ContextMenu">
<MenuItem Header="Copy Plate" Command="cs:CarSystemCommands.CopyPlateCommand" />
<MenuItem Header="Search Plate" Command="cs:CarSystemCommands.SearchPlateCommand" />
</ContextMenu>
<ContextMenu x:Key="TextBoxContextMenu">
<MenuItem Header="_Copy" Command="Copy" />
<MenuItem Header="Copy Plate" Command="cs:CarSystemCommands.CopyPlateCommand" />
<MenuItem Header="Search Plate" Command="cs:CarSystemCommands.SearchPlateCommand" />
</ContextMenu>
</UserControl.Resources>
Я добавил ссылки на контекстные меню в мои TextBlocks. Вот пример:
<Border Background="#FFFFFF78"
BorderBrush="Black"
BorderThickness="2"
ContextMenu="{StaticResource TextBoxContextMenu}"
Grid.Column="0"
Margin="5,10,5,5">
<TextBlock FontSize="18"
FontWeight="Bold"
HorizontalAlignment="Center"
Margin="5"
x:Name="Camera"
VerticalAlignment="Center" />
</Border>
Наконец, я добавил CommbandBindings в UserControl:
<UserControl.CommandBindings>
<CommandBinding Command="Copy" CanExecute="CopyCommand_CanExecute" Executed="CopyCommand_Executed" />
<CommandBinding Command="cs:CarSystemCommands.CopyPlateCommand" CanExecute="CopyCommand_CanExecute" Executed="CopyPlateCommand_Executed" />
</UserControl.CommandBindings>
У меня есть две проблемы со всем этим на сегодняшний день:
Когда я щелкаю правой кнопкой мыши по элементам управления, я вижу меню, но варианты выбора отображаются серым цветом. У меня есть точки останова, размещенные в начале методов CopyCommand_CanExecute, CopyCommand_Executed и CopyPlateCommand_Executed. These breakpoints were hit so far in only one run. I don't know why they were hit that time but not before or since. How do I make sure that the CanExecute method is called every time?
The one time the breakpoints did get hit, the argument's Source property wasn't the control I thought it was, it was the UserControl. I need to know which of the TextBlocks on the UserControl raised the event. Как я могу это сделать?
Тони
Редактировать:
The UserControl also contains a ComboBox control. I've found that the CanExecute methods do get run when I right click on the TextBlocks after I drop down the ComboBox. I don't have to select anything in the combobox, I just have to click on it.
Any ideas what the ComboBox might be doing that my code isn't?
The other thing is that after dropping down the ComboBox, the OriginalSource of the Execute event arguments is the ComboBox. I want to use the same Copy command on several of the TextBlocks, and I need to know which one's Context Menu was used so I know which TextBlock's Text to copy to the clipboard. Помогите!
2 ответа
Эта проблема была решена в моем коде. Оказалось, что проблема заключалась в том, что процессор XAML не смог определить, какова цель команд. То есть он не мог понять, куда отправить команду.
Я смог исправить это с помощью кода в моем коде позади. Я все еще заинтересован в решении XAML для этой проблемы, но у меня не было времени, чтобы разобраться с ним. В то же время решение, которое я реализовал, работает отлично.
Для тех, кто интересуется, вот код, который я написал, который устанавливает цель команды:
private void FixMenuItems( FrameworkElement element, Func<MenuItem, bool> condition ) {
foreach ( MenuItem menuItem in element.ContextMenu.Items ) {
if ( condition( menuItem ) ) {
menuItem.CommandTarget = this;
}
}
}
Чтобы использовать функцию, вы передаете ссылку на элемент управления с контекстным меню, которое вы пытаетесь исправить в методе, вместе с функцией, которая принимает MenuItem
в качестве параметра возвращает истину, если MenuItem's CommandTarget
свойство должно быть установлено для текущего объекта.
Я нашел частичный ответ на мою проблему. Я выяснил, каким образом мой код может определить, какая команда TextBlock была выполнена из ContextMenu. Вместо использования общего ContextMenu для трех TextBlocks, которым требуется эта команда, я создал отдельное ContextMenu для каждого TextBlock. Затем я добавил CommandParameter в пункт меню Копировать для этого TextBlock с именем свойства, которое я хотел скопировать. Затем в обработчике события CopyCommand_Executed я проверяю значение значения e.Parameter и копирую значение соответствующего элемента управления в буфер обмена. Это прекрасно работает.
Однако моя проблема с событиями CanExecute, которые не запускаются, пока я не выберу что-то в ComboBox, остается. Мне все еще нужно выяснить это.
Редактировать:
Что ж, теперь все работает нормально, включая события CanExecute. Я пробовал разные вещи, которые, должно быть, что-то ломали, но теперь, когда у меня работает CommandParameter, все остальное кажется нормальным. Я собираюсь отметить это как ответ.
Второе редактирование:
Ну, на самом деле, все работает на UserControl, над которым я работал, когда я опубликовал это. Но есть еще проблемы.
Упомянутый выше UserControl фактически встроен в другой UserControl. Первый контент UserControl содержится в StackPanel; Я установил StackPanel в качестве FocusScope, и это, кажется, когда все начало работать.
Второй элемент управления имеет StackPanel в корне и несколько гридов внутри него. Первая Grid содержит первый UserControl и некоторые другие вещи. Вторая Grid ниже, которая имеет две DataGrids, которые имеют ContextMenus. Это ContextMenus, которые сейчас не работают.
Я сделал StackPanel FocusScope. Контекстные меню в первом UserControl не будут работать, если я не сделаю его FocusScope, поэтому он тоже один. Наконец, я сделал Grid, который содержит две DataGrids, FocusScope.
Я думаю, что проблема связана с FocusScopes, но я понятия не имею, как это связано, и ни одна комбинация, которую я пробовал, не работает. Есть идеи?