Возник на форумах MSDN вопрос, как привязать команду к контекстному меню. У автора небольшое недопонимание Binding-а, но не суть. Предлагаю посмотреть, как можно создавать объекты их XAML и использовать их, например, как источники в Binding.
Создаем новое WPF приложение и добавляем в него нашу команду:
public void Execute(object parameter)
{
MessageBox.Show("Привет");
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
На форму приложения подключаем пространство имен:
xmlns:local="clr-namespace:WpfApplication2"
И в ресурсах создаем наш объект на основе SimpleCommand:
<Window.Resources>
<ObjectDataProvider ObjectType="{x:Type local:SimpleCommand}" x:Key="comm" />
Ну а теперь добавляем в ресурсы наше контекстное меню:
</ContextMenu>
Я указал наш созданный класс в качестве источника, Path не указываю, т.к. сам объект помещенный в Source нас и интересует. Но можно и классически, объект источника поместить в DataContext:
<MenuItem Header="Hello" Command="{Binding }" DataContext="{StaticResource comm}" />
Для демо, я кинул на форму TextBox и указал у него наше контекстное меню:
<TextBox ContextMenu="{StaticResource Hello}" />
Запускаем:
Ну и два усовершенствования. По-первых, при создании объектов их XAML мы можем передавать в конструктор параметры. Переписываем нашу команду:
private string _message;
public SimpleCommand(string p_message)
{
_message = p_message;
}
public void Execute(object parameter)
{
MessageBox.Show(_message);
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
Подключаем пространство имен System:
xmlns:system="clr-namespace:System;assembly=mscorlib"
И создаем не один объект, а два:
<system:String>Hello</system:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
<ObjectDataProvider ObjectType="{x:Type local:SimpleCommand}" x:Key="commBye">
<ObjectDataProvider.ConstructorParameters>
<system:String>Bye</system:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
Правим контекстное меню (я Key поменял, надо и в TextBox тоже поправить):
<MenuItem Header="Bye" Command="{Binding }" DataContext="{StaticResource commBye}" />
</ContextMenu>
Во-вторых, если бы я решал эту задачу, то я бы добавил в проект еще один класс:
public ICommand Hello { get; set; }
public ICommand Bye { get; set; }
public ContextMenuViewModel()
{
Hello = new SimpleCommand("Hello");
Bye = new SimpleCommand("Bye");
}
}
Ну и окно переписал бы так:
<MenuItem Header="Hello" Command="{Binding Hello}" />
<MenuItem Header="Bye" Command="{Binding Bye}" />
</ContextMenu>
Все.
Создаем новое WPF приложение и добавляем в него нашу команду:
public class SimpleCommand : ICommand
{public void Execute(object parameter)
{
MessageBox.Show("Привет");
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
На форму приложения подключаем пространство имен:
xmlns:local="clr-namespace:WpfApplication2"
И в ресурсах создаем наш объект на основе SimpleCommand:
<Window.Resources>
<ObjectDataProvider ObjectType="{x:Type local:SimpleCommand}" x:Key="comm" />
Ну а теперь добавляем в ресурсы наше контекстное меню:
<ContextMenu x:Key="Hello">
<MenuItem Header="Hello" Command="{Binding Source={StaticResource comm}}" /></ContextMenu>
Я указал наш созданный класс в качестве источника, Path не указываю, т.к. сам объект помещенный в Source нас и интересует. Но можно и классически, объект источника поместить в DataContext:
<MenuItem Header="Hello" Command="{Binding }" DataContext="{StaticResource comm}" />
Для демо, я кинул на форму TextBox и указал у него наше контекстное меню:
<TextBox ContextMenu="{StaticResource Hello}" />
Запускаем:
Ну и два усовершенствования. По-первых, при создании объектов их XAML мы можем передавать в конструктор параметры. Переписываем нашу команду:
public class SimpleCommand : ICommand
{private string _message;
public SimpleCommand(string p_message)
{
_message = p_message;
}
public void Execute(object parameter)
{
MessageBox.Show(_message);
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
Подключаем пространство имен System:
xmlns:system="clr-namespace:System;assembly=mscorlib"
И создаем не один объект, а два:
<ObjectDataProvider ObjectType="{x:Type local:SimpleCommand}" x:Key="commHello">
<ObjectDataProvider.ConstructorParameters><system:String>Hello</system:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
<ObjectDataProvider ObjectType="{x:Type local:SimpleCommand}" x:Key="commBye">
<ObjectDataProvider.ConstructorParameters>
<system:String>Bye</system:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
Правим контекстное меню (я Key поменял, надо и в TextBox тоже поправить):
<ContextMenu x:Key="Menu">
<MenuItem Header="Hello" Command="{Binding }" DataContext="{StaticResource commHello}" /><MenuItem Header="Bye" Command="{Binding }" DataContext="{StaticResource commBye}" />
</ContextMenu>
Во-вторых, если бы я решал эту задачу, то я бы добавил в проект еще один класс:
class ContextMenuViewModel
{public ICommand Hello { get; set; }
public ICommand Bye { get; set; }
public ContextMenuViewModel()
{
Hello = new SimpleCommand("Hello");
Bye = new SimpleCommand("Bye");
}
}
Ну и окно переписал бы так:
<ObjectDataProvider ObjectType="{x:Type local:ContextMenuViewModel}" x:Key="contextMenuViewModel"
/>
<ContextMenu x:Key="Menu" DataContext="{StaticResource contextMenuViewModel}"><MenuItem Header="Hello" Command="{Binding Hello}" />
<MenuItem Header="Bye" Command="{Binding Bye}" />
</ContextMenu>
Все.
Комментариев нет:
Отправить комментарий