Использование команд WPF с Canvas не работает

У меня есть пользовательский холст, полученный из Canvas, Он содержит мало ApplicationCommands лайк New/Open/Save и т.д. добавлено, как это -

this.CommandBindings.Add(new CommandBinding(ApplicationCommands.New, New_Executed, 
New_Enabled));

New_Enabled всегда возвращает истину.

Этот элемент управления используется в проекте wpf, имеющем строку меню; Кнопки меню New/Open/Save находятся в этой строке меню с их Command установить соответствующий ApplicationCommand как это -

<syncfusion:SimpleMenuButton
    x:Name="NewMenu"
    Icon="Images\New_Large.png"
    Label="New"
    IsEnabled="True"
    Command="{x:Static ApplicationCommands.New}"
    syncfusion:Ribbon.KeyTip="N">
</syncfusion:SimpleMenuButton>

Команда работает правильно, когда фокус присутствует на Canvas но как только фокус переключается на другой элемент управления, кнопка "Новый" отключается. Я пробовал настройку CommandTarget в главное окно, но это тоже не работает.

Почему это происходит и как можно убедиться, что кнопка "Новое меню" будет всегда включена?

2 ответа

Решение

@repka - Спасибо за ваш ответ; Я уже пытался использовать имя холста в качестве CommandTarget но это не работает; Кнопки включаются только тогда, когда фокус находится на холсте, как только я нажимаю на какой-то другой элемент управления в окне, они отключаются. Я также пытался использовать IsFocusScope но результат тот же. Спасибо за подсказку имени команды.

Я должен был согласиться с этим обходным путем, хотя я не слишком доволен этим -

    public WindowMain()
    {
        InitializeComponent();

        //Add commnad bindings
        //Need to do this to keep New/Open/Save/Run buttons always enabled
        //ToDo:[AJ] Look for better solution then this
        this.CommandBindings.Add(new CommandBinding(ApplicationCommands.New, this.TheCanvas.New_Executed, this.TheCanvas.New_Enabled));
        this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Open, this.TheCanvas.Open_Executed, this.TheCanvas.Open_Enabled));
        this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Save, this.TheCanvas.Save_Executed, this.TheCanvas.Save_Enabled));
        this.CommandBindings.Add(new CommandBinding(RTDesignerCanvas.Run, this.TheCanvas.Run_Executed));
    }

Проблема в том, что когда ваша кнопка и холст совместно используют область логического фокуса где-то выше в иерархии (скорее всего, это ваше окно), команды, инициированные в некотором меню, никогда не достигают вашего холста.

Если у вас есть только один холст, на который вы хотите получить все ваши команды, просто свяжите CommandTarget из ваших кнопок на холсте:

...
Command="New"
CommandTarget="{Binding ElementName=TheCanvas}"
...

Обратите внимание, что ICommand отмечен TypeConverterAttribute который преобразует строки как "Новый" в ApplicationCommands.New так что вам не нужно использовать x:Static расширение разметки.

Вы можете сделать это в одном месте с Style для всех кнопок на уровне вашего меню / панели инструментов.

Однако, если у вас есть несколько холстов, и вы хотите, чтобы ваша команда была направлена ​​на текущий, вы должны сделать две вещи:

  1. убедитесь, что ваш холст (или элемент управления) имеет Focusable="True"
  2. ограничьте область логического фокуса вашей панели инструментов (или любого контейнера, который вы используете для своих кнопок), установив FocusManager.IsFocusScope="True" в теме. Некоторые контейнеры, такие как меню или ToolBar иметь это по умолчанию. Таким образом, как только алгоритм маршрутизации команд достигнет области действия, он перенаправит его на элемент, в данный момент имеющий фокус клавиатуры.
Другие вопросы по тегам