WPF MVVM - 在VM中显示表单

时间:2015-11-18 09:17:54

标签: c# wpf xaml mvvm

我是MVVM的新手,如果我做错了,请告诉我。

基本上frmEpisodeView.xaml应该是在此处设置的启动窗口:

StartupUri="View/frmEpisodeView.xaml"

当这个窗口加载时,我想检查用户是否已经使用过该应用程序并且有registry key可用。

我已从后面的代码中为datacontext设置frmEpisodeView.xaml,如下所示

DataContext = new EpisodeViewModel();

在我的EpisodeViewModel.cs中,我按逻辑检查注册表项

public EpisodeViewModel() {

    if (Registry.GetValue("HKEY_CURRENT_USER", "URL", "") == null)
    {        
        //OPEN FORM HERE FRMLOGINVIEW.XAML
        ServerURL = Registry.GetValue("HKEY_CURRENT_USER", "URL", "").ToString();
    }
}

在逻辑中,如果注册表项为空,则表单应出现在用户登录的位置,然后将该条目保存在该页面上。

如何让表单显示?

4 个答案:

答案 0 :(得分:3)

最干净,我认为最简单的方法就是写一个帮助类。为此服务创建一个接口,然后实现ShowWindow方法(对象DataContext)以显示您喜欢的窗口并设置datacontext。

class WindowService:IWindowService
{
    public void showWindow<T>(object DataContext) where T: Window, new() 
    {
     ChildWindow window = new T();
     window.Datacontext = DataContext;
     window.Show();
    }
}

另一种非常优雅的方式是使用像这样的动作(Source):

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
        DataContext = new MainViewModel(() => (new Window()).Show()); // would be actual window
    }
}

public class MainViewModel
{
    private Action popupAction;
    public MainViewModel(Action popupAction)
    {
        this.popupAction = popupAction;
    }

    public ICommand PopupCommand { get; set; }

    public void PopupCommandAction()
    {
        popupAction();
    }
}

public class SomeUnitTest
{
    public void TestVM()
    {
        var vm = new MainViewModel(() => { });
    }
}

答案 1 :(得分:0)

所以我最初将这个作为一个简单的例子。

视图模型

public class EpisodeViewModel
{
    private readonly IEpisodeModel episodeModel;

    private readonly IViewFinder viewFinder;

    public EpisodeViewModel(IEpisodeModel episodeModel, IViewFinder viewFnder)
    {
        this.episodeModel = episodeModel;
        this.viewFinder = viewFinder;
        CheckLoginPassed(this.episodeModel.LoginPassed);
    }

    private CheckLoginPassed(bool loginPassed)
    {
        if (!loginPassed)
        {
            this.viewFinder.LoadView<ILoginView>();
        }
    }
}

IView界面

public interface IView
{
    void Show();
}

模型界面

public interface IEpisodeModel
{
    bool LoginPassed
    {
        get;
    }
}

模型

public class EpisodeModel : IEpisodeModel
{
    private bool loginPassed;

    public EpisodeModel()
    {
        if (Registry.GetValue("HKEY_CURRENT_USER", "URL", "") == null)
        {
            loginPassed = false;
        }
    }

    public bool LoginPassed
    {
        get
        {
            return this.loginPassed;
        }
    }
}

IViewFinder界面

public interface IViewFinder
{
    void LoadView<T>();
}

取景

public class ViewFinder : IViewFinder
{
    private readonly IEnumerable<IView> availableViews;

    public ViewFinder(IEnumerable<IView> availableViews)
    {
        this.availableViews = availableViews;
    }

    public void LoadView<T>()
    {
        var type = typeof(T);

        foreach (var view in this.availableViews)
        {
            if (view.GetType().IsAssignableFrom(type))
            {
                view.Show();
            }
        }
    }

我写这篇文章时考虑到了IoC,如果你没有IoC,我真的希望得到一个,因为在解决依赖关系时它将是一个巨大的帮助。这只是一个基本的例子,我可能有一个不同的对象,仅用于检查我向Model提供结果的注册表,但这应该是一个开始。

因此,在引用ILoginView这是一个简单地继承自IView的接口时,它实际上并没有提供任何细节。 IView界面有点奇怪,因为你的视图已经实现了Show方法,只要它们也从'Window'继承,所以实际上你不需要做任何事情,这只是提供了一种更简单的方法来调用显示而不必实际知道您所呼叫的是Window

另一点是我的ViewFinder在这里相对简单,虽然它可以用于一个小项目我可能会看一些类似MVVM Light的东西来管理我的MVVM处理,因为它带有View处理和一个简单的服务定位器作为标准。

答案 2 :(得分:0)

是的,这是执行MVVM时的典型问题。其中许多问题可以概括为:我如何做这个或那个具体的事情&#34;在具体的用户界面中,我应该100%坚持在我的视图模型中?

这种以及许多其他相关问题在https://msdn.microsoft.com/en-us/library/gg406140.aspx(开发人员的Microsoft Prism Library 5.0 for WPF指南)中都有很好的答案,我强烈推荐给您。

就我个人而言,我很高兴看到这本书,作者显然知道他们所表达的内容。

致以最诚挚的问候,

Henrik Dahl

答案 3 :(得分:-1)

您始终可以在App.xaml.cs构造函数中添加视图代码

public App()
{
    if (Registry.GetValue("HKEY_CURRENT_USER", "URL", "") == null)
    {        
        //OPEN FORM HERE FRMLOGINVIEW.XAML
        StartupUri = new Uri("View/frmLoginView.xaml", UriKind.Relative);

        ServerURL = Registry.GetValue("HKEY_CURRENT_USER", "URL", "").ToString();
    }
}