在View-Model [WPF-MVVM]中使用服务方法

时间:2010-12-14 12:17:35

标签: wpf mvvm service mef

您尝试使用MVVM将我的Winform应用程序移植到WPF。我使用Caliburn Micro和MEF作为IoC。我在外部dll服务 - > Pokec_Toolki.dll ,此服务使用其他外部dll,如JSON.NET,HtmlAgilityPack..etc(第三方库)。

我的服务如下:

public interface IPokecConnection
{
    PokecAccount LogOn(string nick, string password);
    bool LogOff(PokecAccount account);
}

[Export(typeof(IPokecConnection))]
public class PokecConnection : IPokecConnection
{
}

对于我的服务我为类PokecConnection创建消费者,它与服务在同一个程序集中:

[Export]
public class PokecConnectionConsumer
{
    private readonly IPokecConnection _pokecConn;

    [ImportingConstructor]
    public PokecConnectionConsumer(IPokecConnection pokecConn)
    {
        _pokecConn = pokecConn;
    }

    public PokecAccount MethodWrapperForLogOn(string name, string  password)
    {
        return _pokecConn.LogOn(name, password);
    }

}

我有2个文本框和1个按钮的简单视图。我在视图模型上将按钮的事件点击与校准惯例绑定。

查看:

<Button Micro:Message.Attach="[Event Click]=[Action LogOn(tbNick.Text,tbPassword.Text)]"
        Content="Prihlás ma"
        Width="100" 
        Grid.Row="2"
        Height="25" Margin="4,4,4,4" />

我需要在视图模型中使用服务方法。所以在视图模型中我有这个:

[Export(typeof(IShellViewModel))]
public class ShellViewModel : Screen, IShellViewModel, IDataErrorInfo
{

    private PokecConnectionConsumer _connConsumer;

    protected override void OnInitialize()
    {
        base.OnInitialize();

        var mycatalog = new AssemblyCatalog(System.Reflection.Assembly.LoadFrom("Pokec_Toolkit.dll"));

        var container = new CompositionContainer(mycatalog);
        container.ComposeParts(this);

        _connConsumer = container.GetExportedValue<PokecConnectionConsumer>();
    }

    //this method is bind on event click of button in view
    public void LogOn(string nick, string password)
    {
        //call method LogOn from class PokecConnection in external dll through PokecConnectionConsumer

        var accout = _connConsumer.MethodWrapperForLogOn(nick, password);

        // in this place if account is not null, I need close this view and create new view MainView 
        //a send to the MainViewModel constructor as argument variable account

        //some test 
        MessageBox.Show(accout.SessionId);
    }


}

我有这些问题:

  1. 首先,创造消费者是好事 对于外部DLL中的服务类? 在我的情况下PokecConnectionConsumer **和这个类在同一个程序集中 作为服务类PokecConnection?
  2. 加载外部是正确的方法     方法中的视图模型中的程序集     OnInitialize?
  3. 这是正确的呼叫服务方法     视图模型?
  4. 如何绑定存在更合适的方式     来自外部dll的方法     控制 ?我需要使用MVVM在wpf应用程序中简单加载外部dll 并在控件上绑定服务方法 在视图中。什么是最好的方式?
  5. 如何关闭实际视图并创建新视图,同时激活此视图。我需要从视图模型发送作为参数变量到另一个vie模型构造函数。**

    我的解决方案:

    我创建了接口程序集,并在外部服务dll和wpf app中引用此程序集。

    在bootstraper中,我用反射加载这个程序集:

        var catalog =
        new AggregateCatalog(
            AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());
    
    catalog.Catalogs.Add(
        new AssemblyCatalog(string.Format(
            CultureInfo.InvariantCulture, "{0}{1}", System.IO.Directory.GetCurrentDirectory(), @"\Pokec_Toolkit.dll")));
    
    _container = new CompositionContainer(catalog);
    

    比我创建指挥班:

    public interface IShellViewModel
    {
        void ShowLogOnView();
        void ShowMessengerView();
    }
    
    [Export(typeof(IShellViewModel))]
    public class ShellViewModel : Conductor<IScreen>, IShellViewModel
    {
        public ShellViewModel()
        {
            ShowLogOnView();
        }
    
        public void ShowLogOnView()
        {
            ActivateItem(IoC.Get<LogOnViewModel>());
        }
    
        public void ShowMessengerView()
        {
            ActivateItem(IoC.Get<MessengerViewModel>());
        }
    }
    

    在视图模型中我有这个:

      [Export]
        public class LogOnViewModel : Screen, IDataErrorInfo, ILogOnViewModel
        {
    
            [Import]
            private IShellViewModel _shellViewModel;
    
            [Import]
            private IPokecConnection _pokecConn;
    
    //this method is bind on event click of button
            public void LogOn(string nick, string password)
            {
                //SHOW NEW WIEW
               _shellViewModel.ShowMessengerView();
            }
        }
    

1 个答案:

答案 0 :(得分:0)

1)是的,这样如果外部依赖关系发生变化,您就不必重新编译UI。它也必须在View / VM逻辑之外。

2)我不害怕。为它创建一个单独的服务类。

3)同样,为它创建一个单独的服务类并在VM中使用。

4)好吧,无论如何你必须加载一个DLL。所以将它加载到服务类中。