Используя WPF, MVVM и Bindings с WinForm UserControl, как успешно интегрироваться? - PullRequest
4 голосов
/ 07 апреля 2011

У меня есть WinForm UserControl внутри окна WPF, и код WPF использует шаблон MVVM.

Каков наилучший способ успешной интеграции элемента управления WinForm в шаблон MVVM? Могу ли я использовать какую-либо форму привязки со стороны WPF?

Допустим, я хочу обработать некоторые события из элемента управления WF, есть ли способ полностью перейти на MVVM?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 08 апреля 2011

Обратите внимание, что это на самом деле не отвечает на вопросы (я должен был прочитать лучше).Если вы заинтересованы в использовании элемента управления WPF в приложении WinForms, вот подход.Мой сценарий: 1) У меня есть элемент управления WinForms, который используется во многих местах моего приложения.2) Хотите разработать реализацию WPF, которая будет использовать шаблон MVVM.3) Хотите написать элемент управления как надлежащий WPF-элемент управления со свойствами зависимостей, чтобы его можно было правильно использовать, когда мое приложение в конечном итоге будет полностью WPF.4) Хотите сохранить тот же элемент управления WinForms и API, чтобы не нарушать существующий клиентский код в моем приложении.

Большинство всего было простым, за исключением того, что мой элемент управления WinForms вызывал события, когда изменялись свойства моего элемента управления WPF.Я хотел использовать привязку, но поскольку источником привязки должен быть DependencyObject, а System.Windows.Forms.UserControl - нет, мне пришлось создать простой вложенный класс.Я написал свой элемент управления WPF точно так же, как если бы я интегрировал его в приложение WPF, и просто сделал несколько дополнительных шагов, чтобы заставить работать мою оболочку WinForms.

Вот код для моего элемента управления WPF:

public partial class MonkeySelector : UserControl
{
  public static readonly DependencyProperty SelectedMonkeyProperty =
    DependencyProperty.Register(
    "SelectedMonkey", typeof(IMonkey),
    typeof(MonkeySelector));

  public MonkeySelector()
  {
    InitializeComponent();
  }

  protected override void OnInitialized(EventArgs e)
  {
    base.OnInitialized(e);

    // Note: No code is shown for binding the SelectedMonkey dependency property
    // with the ViewModel's SelectedMonkey property. This is done by creating
    // a Binding object with a source of ViewModel (Path = SelectedMonkey) and
    // target of the SelectedMonkey dependency property. In my case, my
    // ViewModel was a resource declared in XAML and accessed using the
    // FindResource method.
  }

  public IMonkey SelectedMonkey
  {
    get { return (IMonkey)GetValue(SelectedMonkeyProperty); }
    set { SetValue(SelectedMonkeyProperty, value); }
  }
}

Вот код для моего элемента управления WinForms:

public partial class WinFormsMonkeySelector : UserControl
{
  public event EventHandler SelectedMonkeyChanged;

  private MonkeySelector _monkeySelector;
  private WpfThunker _thunker;

  public WinFormsMonkeySelector()
  {
    InitializeComponent();

    _monkeySelector = new MonkeySelector();
    _elementHost.Child = _monkeySelector;

    System.Windows.Data.Binding binding = new System.Windows.Data.Binding("SelectedMonkey");
    binding.Source = _monkeySelector;
    binding.Mode = System.Windows.Data.BindingMode.OneWay;

    _thunker = new WpfThunker(this);
    // Note: The second parameter here is arbitray since we do not actually
    // use it in the thunker. It cannot be null though. We could declare
    // a DP in the thunker and bind to that, but that isn't buying us anything.
    System.Windows.Data.BindingOperations.SetBinding(
      _thunker,
      MonkeySelector.SelectedMonkeyProperty,
      binding);
  }

  protected virtual void OnSelectedMonkeyChanged()
  {
    if (SelectedMonkeyChanged != null)
      SelectedMonkeyChanged(this, EventArgs.Empty);
  }

  public IMonkey SelectedMonkey
  {
    get { return _monkeySelector.SelectedMonkey; }
    set { _monkeySelector.SelectedMonkey = value; }
  }

  private class WpfThunker : System.Windows.DependencyObject
  {
    private WinFormsMonkeySelector _parent;

    public WpfThunker(WinFormsMonkeySelector parent)
    {
      _parent = parent;
    }

    protected override void OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e)
    {
      base.OnPropertyChanged(e);

      // Only need to check the property here if we are binding to multiple
      // properties.
      if (e.Property == MonkeySelector.SelectedMonkeyProperty)
        _parent.OnSelectedMonkeyChanged();
    }
  }
}
1 голос
/ 07 апреля 2011

Лично я бы справился с этим, создав WPF UserControl, который оборачивает элемент управления Windows Forms.Это позволит вам инкапсулировать весь необходимый код в ваш элемент управления WPF, а затем использовать его в чистом виде MVVM.

Будет трудно оставаться «чистым» MVVM, используя элемент управления Windows Forms напрямую., поскольку для элементов управления Windows Forms обычно требуется другая модель привязки, а также обычно требуется прямая обработка событий.

0 голосов
/ 07 апреля 2011

Вы можете взглянуть на WAF Windows Forms Adapter . Он показывает возможный способ использования Windows Forms вместе с MVVM.

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