Использование команд WPF с Canvas не работает - PullRequest
0 голосов
/ 27 мая 2010

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

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

New_Enabled всегда возвращает true.

Этот элемент управления используется в проекте wpf, имеющем строку меню; Кнопки меню «Создать / Открыть / Сохранить» присутствуют в этой строке меню, и их 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 ]

1 голос
/ 27 мая 2010

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

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

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

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

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

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

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

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

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

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