Привязать событие в пользовательском элементе управления WPF к команде в ViewModel - PullRequest
2 голосов
/ 12 мая 2010

У меня есть пользовательский элемент управления, который имеет событие. У меня есть окно, использующее этот пользовательский элемент управления. Окно привязано к модели представления. Я хотел бы, чтобы событие из пользовательского элемента управления передавалось непосредственно в ICommand моей модели представления. Я явно чувствую себя здесь плотно, так как не могу понять, как это сделать. Любая помощь приветствуется.

Спасибо

Ответы [ 2 ]

2 голосов
/ 13 мая 2010

Если это одноразовый, вы можете использовать простой обработчик событий:

<some:CustomControl SuperDuper="OnSuperDuper" />

с кодом позади

private void OnSuperDuper(object sender, EventArgs e)
{
  _theCommand.Execute(null, (IInputElement)sender);
}

Если вы хотите сделать это несколько раз для определенного события, я бы использовал прикрепленное свойство.

<some:CustomControl my:AttachedEvents.SuperDuperCommand="{Binding TheCommand}" />

, где прикрепленное свойство просто:

// use propa snippet to build this quickly
public static ICommand GetSuperDuperCommand(DependencyObject obj) { return (ICommand)obj.GetValue(SuperDuperCommandProperty); }
public static void SetSuperDuperCommand(DependencyObject obj, ICommand value) { obj.SetValue(SuperDuperCommandProperty, value); }
public static readonly DependencyProperty SuperDuperCommandProperty = DependencyProperty.RegisterAttached("SuperDuperCommand", typeof(ICommand), typeof(AttachedEvents), new PropertyMetadata
{
  PropertyChangedCallback = (obj, e) =>
  {
    if(oldCommand==null) ((CustomControl)obj).SuperDuper += OnSuperDuper;
    if(newCommand==null) ((CustomControl)obj).SuperDuper -= OnSuperDuper;
  }
});

private void OnSuperDuper(object sender, EventArgs e)
{
  var control = (CustomControl)sender;
  GetSuperDuperCommand(sender).Execute(null, sender));
}

Вы можете дополнительно обобщить это, чтобы сопоставить любое событие любой команде, используя MarkupExtension. Вот идея:

<some:CustomControl SuperDuper="{lib:CommandWrapper {Binding TheCommand}}" />

Код выглядит так:

public class CommandWrapper : MarkupExtension
{
  public BindingBase CommandBinding { get; set; }

  public CommandWrapper() {}
  public CommandWrapper(BindingBase commandBinding) { CommandBinding = commandBinding; }

  public object ProvideValue(IServiceProvider serviceProvider)
  {
    return new EventHandler((obj, e) =>
    {
      // Evaluate CommandBinding against obj, fire command
    });
  }
}

Вы можете конкретизировать детали. Обратите внимание, что вместо того, чтобы просто сказать «новый EventHandler», вы можете передать фактический тип обработчика событий в CommandWrapper и использовать отражение для создания соответствующего делегата.

Я не совсем уверен, что синтаксический анализатор XAML позволит вам установить событие, используя MarkupExtension, так что это последнее решение может на самом деле не работать просто. Но если нет, его можно объединить с прикрепленным свойством, например, так:

<some:CustomControl lib:CommandWrapper.Add="{lib:CommandWrapper SuperDuper,{Binding TheCommand}}" />

Это определенно будет работать: CommandWrapper.Add получит имя события из CommandWrapper, созданного расширением разметки, и может создать соответствующее отображение.

0 голосов
/ 12 мая 2010

Если вы хотите направить событие в команду, вы можете использовать прикрепленное свойство. Я использовал этот пример для добавления поддержки команд в событие ComboBox SelectionChanged:

http://blog.fossmo.net/post/How-to-create-an-attached-property-in-WPF-using-a-ComboBox.aspx

Приветствие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...