Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
WPF-практика 5 События и команды.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.21 Mб
Скачать

Привязка команды к прослушивающему элементу

Как только мы присоединим команду к элементу-источнику, он сразу же становится недоступен, как будто бы его свойство IsEnabled приобрело значение false. Это происходит потому, что мы не привязали команду к прослушивающему ее элементу. Как же это сделать?

Любой элемент управления WPF наследует от класса System.Windows. UIElement, который имеет свойство-коллекцию CommandBindings типа CommandBindingCollection, предназначенную для того, чтобы можно было сделать этот элемент прослушивающим команды. В эту коллекцию помещаются специальные объекты привязки CommandBinding, у которых имеется свойство Command и событие Executed. Мы создаем объекты CommandBinding, присоединяем к их свойству Command нужные объекты команд, а к событию Executed - соответствующие обработчики. Затем эти настроенные объекты добавляем в коллекцию CommandBindings элемента. Так элемент становится прослушивающим.

Как уже говорилось, когда источник команды возбуждает присоединенный к нему объект команды, тот последовательно выполняет методы CanExecute() и Execute() интерфейса ICommand. Эти методы генерируют командные события, которые движутся по дереву элементов, проверяя их коллекции CommandBindings с целью обнаружить объект CommandBinding, соответствующий возбужденной команде. Как только такой объект привязки будет обнаружен в прослушивающем команду элементе, немедленно выполнится подписанный на событие Executed обработчик.

В качестве прослушивающего можно сделать любой элемент логического дерева. Но для получения наибольшей гибкости привязки команд рекомендуется добавлять в корневой элемент - окно (или контейнер элемента Page ).

Упражнение 4. Привязка команд в разметке

Построим простое приложение, в котором присоединим библиотечные команды ApplicationCommands. Open и ApplicationCommands. Save, каждую - к двум элементам-источникам: кнопке и главному меню окна. Дополнительным источником команд будет уже встроенная в них клавиатурная комбинация Ctrl+O и Ctrl+S. В качестве прослушивающего элемента выберем окно. В коллекцию CommandBindings окна добавим два объекта привязки CommandBinding, связывающие между собой команду и обработчик. Привязку выполним в разметке XAML.

  • Добавьте к решению командой оболочки File/Add/New Project новый проект с именем BindingCommandsXAML и назначьте его стартовым в панели Solution Explorer командой контекстного меню Set as StartUp Project

увеличить изображение

  • Заполните файл разметки Window1.xaml следующим кодом

<Window x:Class="BindingCommandsXAML.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="Window1: Декларативная привязка" Height="300" Width="300"

Background="#FFD4D0C8"

WindowStartupLocation="CenterScreen"

>

<StackPanel Margin="5">

<Menu>

<MenuItem Header="_File">

<MenuItem Command="ApplicationCommands.Open" />

<MenuItem Command="ApplicationCommands.Save" />

</MenuItem>

</Menu>

<Button Margin="5" Padding="5" Focusable="False"

Command="ApplicationCommands.Open"

Content="Open"

/>

<Button Margin="5" Padding="5" Focusable="False"

Command="ApplicationCommands.Save"

Content="Save"

/>

</StackPanel>

</Window>

Мы присоединили к интерфейсным элементам объекты команд и сделали их таким образом источниками этих команд.

  • Запустите проект и убедитесь, что источники команд не получают фокус ввода и являются недоступными

Несмотря на то, что в элементах меню нами не были заданы атрибуты Header, команды сами прописали нужные названия команд и добавили подсказки для горячих клавиш.

  • Добавьте в разметку объекты привязки следующим образом

<Window x:Class="BindingCommandsXAML.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="Window1: Декларативная привязка" Height="300" Width="300"

Background="#FFD4D0C8"

WindowStartupLocation="CenterScreen"

>

<Window.CommandBindings>

<CommandBinding

Command="ApplicationCommands.Open"

Executed="OpenCommand_Executed">

</CommandBinding>

<CommandBinding

Command="ApplicationCommands.Save"

Executed="SaveCommand_Executed">

</CommandBinding>

</Window.CommandBindings>

<StackPanel Margin="5">

<Menu>

<MenuItem Header="_File">

<MenuItem Command="ApplicationCommands.Open" />

<MenuItem Command="ApplicationCommands.Save" />

</MenuItem>

</Menu>

<Button Margin="5" Padding="5" Focusable="False"

Command="ApplicationCommands.Open"

Content="Open"

/>

<Button Margin="5" Padding="5" Focusable="False"

Command="ApplicationCommands.Save"

Content="Save"

/>

</StackPanel>

</Window>

  • Вызовите контекстное меню для записей привязки обработчиков и командой Navigate to Event Handler создайте заготовки обработчиков в файле процедурного кода

  • Запустите приложение и убедитесь, что источники команд стали доступными, хотя обработчики еще пустые

  • В меню оболочки командой Project/Add Reference добавьте к текущему проекту ссылку на библиотечную сборку System.Windows.Forms.dll

Мы уже обсуждали ранее, что нельзя напрямую размещать в окне WPF интерфейсные элементы Windows Forms, для этого предназначен переходной контейнер <WindowsFormsHost>. Но в нашем случае мы будем открывать самостоятельные диалоговые окна Windows Forms и не собираемся смешивать в одном окне интерфейсные элементы из разных технологий.

  • Дополните в процедурном файле Window1.xaml.cs класс Window1 следующим кодом

public partial class Window1 : Window

{

public Window1()

{

InitializeComponent();

}

// Обработчик команды Open

System.Windows.Forms.OpenFileDialog openFileDialog = null;

private void OpenCommand_Executed(object sender, ExecutedRoutedEventArgs e)

{

if (openFileDialog == null)

openFileDialog = new System.Windows.Forms.OpenFileDialog();

openFileDialog.ShowDialog();

this.Focus();

}

// Обработчик команды Save

System.Windows.Forms.SaveFileDialog saveFileDialog = null;

private void SaveCommand_Executed(object sender, ExecutedRoutedEventArgs e)

{

if (saveFileDialog == null)

saveFileDialog = new System.Windows.Forms.SaveFileDialog();

saveFileDialog.ShowDialog();

this.Focus();

}

}

  • Запустите приложение и испытайте возможность запуска каждой команды через любой из трех источников: кнопку, меню или клавиатурную комбинацию

Рекомендуется при совместном использовании библиотек WPF и Windows Forms не подключать пространство имен System.Windows.Forms в инструкции using, а использовать полное имя требуемых классов Windows Forms, что мы и сделали. Это нужно для того, чтобы избежать конфликта имен, поскольку в библиотеках разных технологий встречаются типы с одинаковыми именами, например, Color, Pen, Brush.