MVVMLight在设计时显示页面

时间:2018-03-13 03:33:59

标签: c# wpf mvvm-light

我正在努力获得Laurent Bugnion在他的一些视频中谈论的精彩设计时间体验。这是Win7机器上VS2017社区中的WPF应用程序。

在窗口中,FRAME控件绑定到URI。 Source =“{Binding FrameUri,Mode = TwoWay}”程序在运行时工作,但在设计时,我有以下链接到框架中显示的URL(见第一张图片)。

值得注意的是,MainPage有MainViewModel,IntroPage也有自己的viewmodel(IntroViewModel)。

设计时间图像
enter image description here

RUNTIME IMAGE

enter image description here

我猜测Intro页面在设计时没有实例化,但不知道如何做。我试图在Frame xaml中添加一个设计时间线,但这不起作用:d:DataContext =“{d:DesignInstance viewModels:PageViewModel,IsDesignTimeCreatable = True}”

我也尝试在XAML中添加Path = IntroPageViewModel,但这也不起作用。

我在这里有代码:https://github.com/floppydisk525/MvvmLight_WPF_Frame_Nav/tree/NavTest

这是代码:
APP.XAML文件

    <Application.Resources>
        <!--Global View Model Locator-->
        <vm:ViewModelLocator x:Key="Locator"
                             d:IsDataSource="True" />
        <DataTemplate DataType="{x:Type vm:IntroViewModel}">
            <v:IntroPage/>
        </DataTemplate>
    </Application.Resources>    
</Application>

FRAME代码:

<Frame  x:Name="MainFrameDS" Source="{Binding FrameUri, Mode=TwoWay}" HorizontalAlignment="Left" Height="211" Margin="109,88,0,0" VerticalAlignment="Top" Width="258"/>

FRAME URI PROPERTY:

        public const string FrameUriPropertyName = "FrameUri";

    private Uri _frameUri;

    /// <summary>
    /// Sets and gets the FrameUri property.
    /// Changes to that property's value raise the PropertyChanged event. 
    /// </summary>
    public Uri FrameUri
    {
        get
        {
            return _frameUri;
        }
        set
        {
            Set(FrameUriPropertyName, ref _frameUri, value);
            System.Diagnostics.Debug.WriteLine(_frameUri.ToString(), "_frameUri");
            System.Diagnostics.Debug.WriteLine(FrameUri.ToString(), "FrameUri");
        }
    }

FROM ViewModelLocator

public class ViewModelLocator
{
    public static readonly Uri IntroPageUri = new Uri("/IntroPage.xaml", UriKind.Relative);
    public static readonly Uri MiddlePageUri = new Uri("/MiddlePage.xaml", UriKind.Relative);
    public static readonly Uri LastPageUri = new Uri("/LastPage.xaml", UriKind.Relative);

    static ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        if (ViewModelBase.IsInDesignModeStatic)
        {
            SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
        }
        else
        {
            SimpleIoc.Default.Register<IDataService, DataService>();
        }

        var NavigationService = new NavigationService();
        SimpleIoc.Default.Register<INavigationService, NavigationService>();

        SimpleIoc.Default.Register<MainViewModel>();
        SimpleIoc.Default.Register<IntroViewModel>();
        SimpleIoc.Default.Register<MiddleViewModel>();
        SimpleIoc.Default.Register<LastViewModel>();

`#if DEBUG
        if (ViewModelBase.IsInDesignModeStatic)
        {
            var instance = SimpleIoc.Default.GetInstance<IntroViewModel>();
        }
 `#endif
    }

2 个答案:

答案 0 :(得分:1)

  

我猜测在设计过程中没有实例化Intro Page   时间,但不知道该怎么做。我试着添加一个设计时间线   Frame xaml,但是没有用:d:DataContext =&#34; {d:DesignInstance   viewModels:PageViewModel,IsDesignTimeCreatable = True}&#34;

单独的xaml部分是不够的。 要在设计时实例化视图模型,您应该在ViewModelLocator中使用&#34; ViewModelBase.IsInDesignModeStatic&#34;

if (ViewModelBase.IsInDesignModeStatic)
{
    SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
    SimpleIoc.Default.Register<IDataService, DataService>();         
}
如果您需要更多信息,

This似乎是一篇不错的文章。

答案 1 :(得分:0)

我偶然发现了一个解决方案,尽管有一个新问题。

我正在尝试不同的事情,最近一次来自stackoverflow example。我在github MvvmLight_Frame_DesignTime上有一个工作解决方案,有更详细的写作和图片。

解决方案

首先在MainWindow.xaml文件中添加以下行。

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ignore="http://www.galasoft.ch/ignore"
xmlns:v="clr-namespace:MvvmLight_Frame_DesignTime"

然后,Frame控件将d:designtime代码与Content Property一起添加。

<Frame HorizontalAlignment="Left" Height="237" Margin="25,120,0,0" VerticalAlignment="Top" Width="243"
    d:DataContext="{d:DesignInstance Type=v:IntroPage, IsDesignTimeCreatable=True}" 
    Content ="{Binding}"                 
    Source="{Binding FrameUri}"/>

备注

需要注意的重要一点是,我没有从Viewmodel代码或代码后面的代码实例化Frame或Page控件,就像上面的堆栈溢出示例一样。这使得解决方案非常简单且代码很少。

问题

可以使用Source&amp;框架的内容属性?可以这样做吗?
我认为它的工作方式是在设计模式下,DesignInstance使用Type = v:IntroPage进行实例化,并绑定到Content属性。在运行时期间,由于未创建IntroPage类型且MainViewModel FrameUri属性绑定到Frame Source,因此优先。似乎工作,不知道它可能产生什么问题。