2010-12-22 73 views
7

這不僅僅是一個問題的評論,儘管反饋會很好。我的任務是爲我們正在進行的新項目創建用戶界面。我們想要使用WPF,並且我想了解所有現有的可用UI設計技術。由於我對WPF相當陌生,我一直在研究可用的東西。我想我使用MVVM Light Toolkit的主要原因在於它的「Blendability」和EventToCommand行爲!),但我也希望將IoC也納入其中。所以,這就是我所提出的。我修改了MVVM Light項目中的默認ViewModelLocator類,以使用UnityContainer處理依賴注入。考慮到3個月前我不知道這些術語的90%是什麼意思,我想我正走在正確的軌道上。結合MVVM Light Toolkit和Unity 2.0

// Example of MVVM Light Toolkit ViewModelLocator class that implements Microsoft 
// Unity 2.0 Inversion of Control container to resolve ViewModel dependencies. 

using Microsoft.Practices.Unity; 

namespace MVVMLightUnityExample 
{ 
    public class ViewModelLocator 
    { 
     public static UnityContainer Container { get; set; } 

     #region Constructors 
     static ViewModelLocator() 
     { 
      if (Container == null) 
      { 
       Container = new UnityContainer(); 

       // register all dependencies required by view models 
       Container 
        .RegisterType<IDialogService, ModalDialogService>(new ContainerControlledLifetimeManager()) 
        .RegisterType<ILoggerService, LogFileService>(new ContainerControlledLifetimeManager()) 
        ; 
      } 
     } 

     /// <summary> 
     /// Initializes a new instance of the ViewModelLocator class. 
     /// </summary> 
     public ViewModelLocator() 
     { 
      ////if (ViewModelBase.IsInDesignModeStatic) 
      ////{ 
      //// // Create design time view models 
      ////} 
      ////else 
      ////{ 
      //// // Create run time view models 
      ////} 

      CreateMain(); 
     } 

     #endregion 

     #region MainViewModel 

     private static MainViewModel _main; 

     /// <summary> 
     /// Gets the Main property. 
     /// </summary> 
     public static MainViewModel MainStatic 
     { 
      get 
      { 
       if (_main == null) 
       { 
        CreateMain(); 
       } 
       return _main; 
      } 
     } 

     /// <summary> 
     /// Gets the Main property. 
     /// </summary> 
     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", 
      "CA1822:MarkMembersAsStatic", 
      Justification = "This non-static member is needed for data binding purposes.")] 
     public MainViewModel Main 
     { 
      get 
      { 
       return MainStatic; 
      } 
     } 

     /// <summary> 
     /// Provides a deterministic way to delete the Main property. 
     /// </summary> 
     public static void ClearMain() 
     { 
      _main.Cleanup(); 
      _main = null; 
     } 

     /// <summary> 
     /// Provides a deterministic way to create the Main property. 
     /// </summary> 
     public static void CreateMain() 
     { 
      if (_main == null) 
      { 
       // allow Unity to resolve the view model and hold onto reference 
       _main = Container.Resolve<MainViewModel>(); 
      } 
     } 

     #endregion 

     #region OrderViewModel 

     // property to hold the order number (injected into OrderViewModel() constructor when resolved) 
    public static string OrderToView { get; set; } 

     /// <summary> 
     /// Gets the OrderViewModel property. 
     /// </summary> 
     public static OrderViewModel OrderViewModelStatic 
     { 
      get 
      { 
       // allow Unity to resolve the view model 
       // do not keep local reference to the instance resolved because we need a new instance 
       // each time - the corresponding View is a UserControl that can be used multiple times 
       // within a single window/view 
       // pass current value of OrderToView parameter to constructor! 
       return Container.Resolve<OrderViewModel>(new ParameterOverride("orderNumber", OrderToView)); 
      } 
     } 

     /// <summary> 
     /// Gets the OrderViewModel property. 
     /// </summary> 
     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", 
      "CA1822:MarkMembersAsStatic", 
      Justification = "This non-static member is needed for data binding purposes.")] 
     public OrderViewModel Order 
     { 
      get 
      { 
       return OrderViewModelStatic; 
      } 
     } 
     #endregion 

     /// <summary> 
     /// Cleans up all the resources. 
     /// </summary> 
     public static void Cleanup() 
     { 
      ClearMain(); 
      Container = null; 
     } 
    } 
} 

而MainViewModel類表示依賴注入用法:

using GalaSoft.MvvmLight; 
using Microsoft.Practices.Unity; 

namespace MVVMLightUnityExample 
{ 
    public class MainViewModel : ViewModelBase 
    { 
     private IDialogService _dialogs; 
     private ILoggerService _logger; 

     /// <summary> 
     /// Initializes a new instance of the MainViewModel class. This default constructor calls the 
     /// non-default constructor resolving the interfaces used by this view model. 
     /// </summary> 
     public MainViewModel() 
      : this(ViewModelLocator.Container.Resolve<IDialogService>(), ViewModelLocator.Container.Resolve<ILoggerService>()) 
     { 
      if (IsInDesignMode) 
      { 
       // Code runs in Blend --> create design time data. 
      } 
      else 
      { 
       // Code runs "for real" 
      } 
     } 

     /// <summary> 
     /// Initializes a new instance of the MainViewModel class. 
     /// Interfaces are automatically resolved by the IoC container. 
     /// </summary> 
     /// <param name="dialogs">Interface to dialog service</param> 
     /// <param name="logger">Interface to logger service</param> 
     public MainViewModel(IDialogService dialogs, ILoggerService logger) 
     { 
      _dialogs = dialogs; 
      _logger = logger; 

      if (IsInDesignMode) 
      { 
       // Code runs in Blend --> create design time data. 
       _dialogs.ShowMessage("Running in design-time mode!", "Injection Constructor", DialogButton.OK, DialogImage.Information); 
       _logger.WriteLine("Running in design-time mode!"); 
      } 
      else 
      { 
       // Code runs "for real" 
       _dialogs.ShowMessage("Running in run-time mode!", "Injection Constructor", DialogButton.OK, DialogImage.Information); 
       _logger.WriteLine("Running in run-time mode!"); 
      } 
     } 

     public override void Cleanup() 
     { 
      // Clean up if needed 
      _dialogs = null; 
      _logger = null; 

      base.Cleanup(); 
     } 
    } 
} 

而OrderViewModel類:

using GalaSoft.MvvmLight; 
using Microsoft.Practices.Unity; 

namespace MVVMLightUnityExample 
{ 
    /// <summary> 
    /// This class contains properties that a View can data bind to. 
    /// <para> 
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel. 
    /// </para> 
    /// <para> 
    /// You can also use Blend to data bind with the tool's support. 
    /// </para> 
    /// <para> 
    /// See http://www.galasoft.ch/mvvm/getstarted 
    /// </para> 
    /// </summary> 
    public class OrderViewModel : ViewModelBase 
    { 

     private const string testOrderNumber = "123456"; 
     private Order _order; 

     /// <summary> 
     /// Initializes a new instance of the OrderViewModel class. 
     /// </summary> 
     public OrderViewModel() 
      : this(testOrderNumber) 
     { 

     } 

     /// <summary> 
     /// Initializes a new instance of the OrderViewModel class. 
     /// </summary> 
     public OrderViewModel(string orderNumber) 
     { 
      if (IsInDesignMode) 
      { 
       // Code runs in Blend --> create design time data. 
       _order = new Order(orderNumber, "My Company", "Our Address"); 
      } 
      else 
      { 
       _order = GetOrder(orderNumber); 
      } 
     } 

     public override void Cleanup() 
     { 
      // Clean own resources if needed 
      _order = null; 

      base.Cleanup(); 
     } 
    } 
} 

這可以用於爲特定顯示的順序視圖的代碼順序:

public void ShowOrder(string orderNumber) 
{ 
    // pass the order number to show to ViewModelLocator to be injected 
    //into the constructor of the OrderViewModel instance 
    ViewModelLocator.OrderToShow = orderNumber; 

    View.OrderView orderView = new View.OrderView(); 
} 

這些示例已被精簡,僅顯示IoC創意。它耗費了大量的試驗和錯誤,在互聯網上搜索示例,並發現Unity 2.0文檔缺乏(在示例代碼中用於擴展)以提出該解決方案。如果您認爲可以改進,請告訴我。

+0

我很想知道你覺得Unity文檔中有什麼漏洞。你還需要什麼呢? – 2010-12-23 04:46:31

+0

Unity文檔非常好,我只是很難找到2.0版的任何示例代碼片段,尤其是使用擴展。 1.x有很多示例代碼,但很多都是過時的(我不斷收到消息,不使用該語法來做事情,因爲使用擴展可以使用新的語法)。 – acordner 2010-12-30 17:27:01

回答

1

首先,您應該避免服務定位器反模式。

其次,每次你想獲得一個OrderView時,你必須設置一個靜態變量?這是一個非常醜陋的設計。