Создать собственное событие для UserControl
У меня, например, есть UserControl, который является шаблоном для отображения студента в списке. Можно абстрагироваться от его содержимого.
Я хочу создать для него событие Click, подобно кнопке, которая берет обработчик события из класса вызвавшего его (например, window). Возможно ли создать такое событие (по подобию DependencyProoerty)? Чтобы была возможность просто передать метод в разметке (опять же подобно событию click у button). Ну или другие события (при наведении мыши на usercontrol и т.п.)
Ответы (1 шт):
Самый простой вариант думаю будет такой:
Допустим у нас есть некий UserControl, который является оберткой над Button и нам надо от него пробросить "органы управления" наружу. Делаем нужные DependencyProperty, я сделаю всего два:
Text- Будет отвечать за написанный текст на кнопке.Command- Отвечает за клик по этой кнопке.
Получаем в итоге такое:
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(UserControl1), new PropertyMetadata(default));
public ICommand Command
{
get => (ICommand)GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(UserControl1), new PropertyMetadata(default));
В XAML будет просто:
<UserControl ...
Name="uc">
<Grid>
<Button Content="{Binding Text, ElementName=uc}" Command="{Binding Command, ElementName=uc}"/>
</Grid>
</UserControl>
Собственно все, мы пробросили два свойства и теперь смело можем их использовать:
<local:UserControl1 Text="Привет мир!" Command="{Binding ClickCommand}"/>
Если нам все же нужны именно события (а все события в WPF заменяются без проблем на комманды и не ясно зачем это может понадобиться), то для таких целей существует маршрутизация событий. Выглядеть это будет примерно так:
public static readonly RoutedEvent ButtonClickEvent =
EventManager.RegisterRoutedEvent("ButtonClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(UserControl1));
public event RoutedEventHandler ButtonClick
{
add => AddHandler(ButtonClickEvent, value);
remove => RemoveHandler(ButtonClickEvent, value);
}
private void Button_Click(object sender, RoutedEventArgs e)
=> RaiseEvent(new RoutedEventArgs(ButtonClickEvent));
Сама кнопка в XAML контрола будет такой:
<Button Content="{Binding Text, ElementName=uc}" Click="Button_Click"/>
Теперь наш контрол пробрасывает событие наружу, и мы смело можем его использовать, как и раньше любое другое событие:
<local:UserControl1 Text="Привет мир!" ButtonClick="UserControl1_ButtonClick" />
Обработчик события
private void UserControl1_ButtonClick(object sender, RoutedEventArgs e)
=> Debug.WriteLine("Клик по кнопке");
Вот так довольно просто мы можем манипулировать событиями контрола, а сами события, в большинстве случаев, достаточно тех, что есть у стандартных объектов, допустим нам нужен клик - оборачиваем, например <Border> или что-либо другое в <Button>, убираем у него весь стиль (делаем прозрачный, без бордюров и др.) и все, у нас готов элемент, который обрабатывает клики.