2011-04-07 60 views

回答

1

個人而言,我會通過創建一個包裝Windows窗體控件的WPF UserControl來處理此問題。這將允許您將所有必需的代碼隱藏到您的WPF控件中,然後以純MVVM方式使用它。

由於Windows窗體控件通常需要不同的綁定模型,並且通常需要直接事件處理,所以直接使用Windows窗體控件很難保持「純粹」MVVM。

+0

因此,有一個WPF用戶控件封裝的WinForms控制,我可以提供WPF從WPF用戶控件綁定但內部它會處理WinForms控件?如果是這樣,那麼它可能就是我想要的方式。 – 2011-04-07 18:51:49

+0

@Stecy:是的 - 在內部,它將最終完成從WPF DependencyProperties到設置控件值,接收事件等的映射。但是,從WPF方面來看,這看起來好像正常的WPF控件。從長遠來看,IMO確實是最好的方式。 – 2011-04-07 18:55:17

2

請注意,這並不真正回答問題(我應該讀得更好)。如果您有興趣在WinForms應用程序中使用WPF控件,請使用下面的方法。我的方案是: 1)有一個WinForms控件在我的應用程序中使用很多地方。 2)要開發一個WPF實現,它將使用MVVM模式。 3)想要將控件編寫爲具有依賴屬性的完整WPF控件,以便在我的應用程序最終都是WPF時正確使用它。 4)想要保持相同的WinForms控件和API不會破壞我的應用程序中的現有客戶端代碼。

除了讓我的WinForms控件在我的WPF控件的屬性更改時引發事件以外,大多數情況都很簡單。我想使用綁定,但由於綁定的來源必須是DependencyObject,而System.Windows.Forms.UserControl不是,我必須製作一個簡單的嵌套類。我寫了我的WPF控件,就好像我將它集成到WPF應用程序中一樣,只是做了一些額外的thunking讓我的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(); 
    } 
    } 
}