【问题标题】:MVVMLight Display Page in Frame during Design TimeMVVMLight 在设计时在框架中显示页面
【发布时间】:2018-03-13 03:33:58
【问题描述】:

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

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

需要指出的是,MainPage 有它的 MainViewModel,而 IntroPage 也有它自己的视图模型 (IntroViewModel)。

设计时间图片

运行时图像

我猜 Intro Page 没有在设计时实例化,但不知道该怎么做。我尝试将设计时间线添加到 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>

帧代码:

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

帧 URI 属性:

        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");
        }
    }

来自 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
    }

【问题讨论】:

    标签: c# wpf mvvm-light


    【解决方案1】:

    我猜 Intro Page 在设计期间没有实例化 时间,但不知道该怎么做。我试图添加一个设计时间线 Frame xaml,但这不起作用:d:DataContext="{d:DesignInstance viewModels:PageViewModel, IsDesignTimeCreatable=True}"

    仅 xaml 部分是不够的。 要在设计时实例化您的视图模型,您应该在 ViewModelLocator 中使用 "ViewModelBase.IsInDesignModeStatic"

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

    如果您需要更多信息,This 似乎是一篇不错的文章。

    【讨论】:

    • 这是 Laurent 的一篇出色的文章......我正在努力解决的实现问题是 URI 绑定到框架的源属性(有效),但是框架显示 URI 链接的文本,而不是页面。我不确定这是数据模板还是页面实例化问题。我不确定如何将 URI 链接到页面的静态 (?) 实例。我确实尝试了文章中的#DEBUG var instance = SimpleIoc.Default.GetInstance();但是,我在主视图模型中将实例设置为什么?只是困惑。
    • @FloppyDisk 由于它在运行时工作并且您已经使用 DataTemplate 将您的 IntroPage 映射到您的 IntroViewModel 我认为在设计时 IntroViewModel 没有被实例化(因此它只显示 URI 的名称)。这就是为什么我建议您在将 IntroViewModel 注册到 ViewModelLocator 之前检查“IsInDesignModeStatic”的原因。不过只是猜测。
    • 我在最初的帖子(最后)中更新了 viewmodelLocator 代码,并使用了我尝试过的方法,但没有成功。不知何故,我错过了语法。
    • @FloppyDisk 也许是框架本身需要指定。我在另一篇文章中找到了this。也许这会有所帮助。
    • 该死的看到你已经尝试过了。奇怪的是视图模型被实例化/注册,并且框架也被配置为设计时数据。唯一的猜测是我还必须为设计时数据(如框架)配置数据模板,但老实说,我不知道语法如何(或者它是否正确^^)。
    【解决方案2】:

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

    我正在尝试不同的东西,最近来自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 控件与 Content 属性一起添加了 d: 设计时代码。

    <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 控件,就像上面关于堆栈溢出的示例一样。这使得解决方案非常简单且代码很少。

    问题

    可以为 Frame 使用 Source & Content 属性吗?这可以做不同的吗?
    我认为它的工作方式是在设计模式下, DesignInstance 使用 Type=v:IntroPage 实例化并绑定到 Content 属性。在运行时,由于未创建 IntroPage 类型并且 MainViewModel FrameUri 属性绑定到 Frame Source,因此优先。似乎有效,不知道会出现什么问题。

    【讨论】:

      猜你喜欢
      • 2017-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-14
      • 2020-01-29
      • 2017-09-13
      • 1970-01-01
      • 2021-11-17
      相关资源
      最近更新 更多