2015-10-08 5 views
2

Я работаю над унаследованным продуктом, в котором все до сих пор было сделано с использованием оконных форм. Из-за требований, связанных с высоким использованием XML, я использую WPF из-за простоты привязки. Я использую модель MVVM, так как требование требует разных представлений, но не имеет большого значения в бизнес-логике. У меня есть пользовательский элемент управления, в котором есть кнопка для открытия формы окна. И этот пользовательский элемент управления снова находится в разных формах окон.Открыть форму окна из ViewModel

Это код для моего XAML, связанный с кнопкой:

<UserControl x:Name="ctrlTemplate" x:Class= "CtrlTemplate" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:WPFControl.UI" 
      xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
      xmlns:xckt="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit" 
      mc:Ignorable="d" 
      DataContext="{DynamicResource ViewModel}"> 
    <UserControl.Resources> 
      <local:ViewModel x:Key="ViewModel" /> 
     </ResourceDictionary> 
    </UserControl.Resources> 

И здесь является обязательной командой с помощью кнопки

<Button x:Name="btnOpenWindowsUI" Command="{Binding OpenWindowsUI, Source={StaticResource ViewModel}}" CommandParameter={????} > 

Моих ViewModel, как это:

public class ViewModel : ViewModelBase 
{ 
    public ICommand OpenWindowsUI{ get; set; } 
    public OTCViewModel() 
    { 
     OpenWindowsUI= new OpenWindowsUI(this); 
    } 
} 

И моя команда выглядит так:

class OpenWindowsUI: ICommand 
{ 
    private ViewModel _mvModel; 
    public event EventHandler CanExecuteChanged 
    { 
     add { } 
     remove { } 
    } 
    public ClearAllData(ViewModel mvModel) 
    { 
     _mvModel = mvModel; 
    } 

    public bool CanExecute(object parameter) 
    { 
     return true; 
    } 

    public void Execute(object parameter) 
    { 
     IWindowsUI indowsUIInstance = null; 
     windowsUIInstance = _container.Resolve<IWindowsUI >(); 
     frmWindowsUI = windowsUIInstance.Reference(); 
     frmWindowsUI.Owner = this; **//How can we specify the parent of this chid form?** 
     frmWindowsUI.ShowInTaskbar = false; 
     windowsUIInstance.SetUp(); 
     frmWindowsUI.Show(); 
     frmWindowsUI.FormClosed += frmWindowsUI_FormClosed; 
    } 
} 

Я знаю, что можно легко найти родительскую форму из кода UserControl, используя следующий фрагмент кода:

public Form FindParentWindowsForm() 
{ 
    var source = (HwndSource)PresentationSource.FromDependencyObject(btnOpenWindowsUI); 
    Form form; 
    if (source != null) 
    { 
     var host = (System.Windows.Forms.Integration.ElementHost)System.Windows.Forms.Control.FromChildHandle(source.Handle); 
     if (host != null) 
     { 
      form = (Form)host.TopLevelControl; 
     } 
    } 
    return form; 
} 

Так вот мои вопросы:

  1. Есть ли способ передать элемент пользовательского интерфейса от элемента управления до ViewModel?

  2. Должен ли мы передать ссылку на элемент пользовательского интерфейса на ViewModel?

  3. Если нет, то что это лучший способ решить вышеуказанную проблему?

ответ

0
  1. Да, вы можете.
  2. Нет. Вы не должны передавать элемент пользовательского интерфейса в ViewModel в MVVM.
  3. Вы можете создать отдельный элемент управления и привязать его к виду. Создайте определенное свойство зависимостей в элементе управления. Измените значение свойства через ViewModel. Поскольку вы можете изменить значение, элемент управления получает свойство зависимостей, которое имеет теперь визуальное дерево элементов управления в окне.

Пожалуйста, обратитесь http://social.technet.microsoft.com/wiki/contents/articles/31416.wpf-mvvm-friendly-user-notification.aspx#ConfirmationRequestor

1

Я не полное решение для вас, однако:

.1. Да. Вы можете - Например, ниже код передаст весь объект Window в качестве параметра CommandParameter:

<button [...] CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/> 

.2. Этот вопрос является темой для типичных дебатов MVVM. С одной стороны, UIElement - это просто объект, который в точке высокого уровня View не отличается от других объектов, таких как Properties, но, с другой стороны, передача UIElement в качестве параметра вызывает нарушение MVVM, поскольку с этого момента ViewModel будет знать о вид.

.3. У вас есть доступ к элементу, который вы хотите передать внутри своего пользовательского элемента управления каким-либо образом?