在WPF中可以使用哪些方法来虚拟设计时数据?


97

我在没有表达式混合的情况下工作,仅在vs2010中使用XAML编辑器。抛开这种智慧,我越来越看到对设计时数据绑定的需求。对于简单的情况,该FallbackValue属性可以很好地工作(文本框和文本块等)。但是尤其是在处理ItemsControl类似内容时,确实需要在设计器中显示示例数据,以便您可以调整和调整控件和数据模板,而不必运行可执行文件。

我知道ObjectDataProvider可以绑定到一个类型,因此可以提供设计时数据以进行可视化,但是在通过加载两个设计时间来加载时,需要进行一些努力以允许真实的运行时数据绑定而不会浪费资源,虚拟数据和运行时绑定。

我真正想要的是能够在XAML设计器中将“ John”,“ Paul”,“ George”和“ Ringo”显示为样式元素ItemsControl,但在应用程序中显示真实数据的能力运行。

我也知道Blend允许一些定义设计时绑定数据的特殊属性,WPF在运行时条件下会有效地忽略这些数据。

所以我的问题是:

1.如何在Visual Studio XAML设计器中利用集合的设计时绑定和非平凡的数据,然后平稳地交换到运行时绑定?

2.其他人如何解决此设计时与运行时数据问题?就我而言,我不能很轻易地对两者使用相同的数据(就像使用数据库查询一样)。

3.它们可以替代我用于数据集成XAML设计的表达式混合吗?(我知道有一些替代方法,但是我特别想要我可以使用的东西并查看绑定的样本数据,等等?)

Answers:


120

使用VS2010,您可以使用设计时属性(适用于SL和WPF)。无论如何,我通常都会有一个模拟数据源,所以这只是一个问题:

  • 添加名称空间声明

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  • 将模拟数据上下文添加到窗口/控件资源

    <UserControl.Resources>
      <ViewModels:MockXViewModel x:Key="DesignViewModel"/>
    </UserControl.Resources>
  • 设置设计时数据上下文

    <Grid d:DataContext="{Binding Source={StaticResource DesignViewModel}}" ...

效果很好。


2
如果您正在使用有问题d:DataContext:你会发现在这个问题上有所帮助stackoverflow.com/questions/8303803/...
马丁Liversage

27
此示例是否会导致将MockXViewModel的实例加载到您的资源中以进行版本构建?这不是问题吗?
jpierson 2012年

12
仅供参考:您还需要以下内容,否则VS2012编译器将不会编译xaml文件:xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d"
Orion Edwards

51
jpierson是正确的。我更喜欢使用<Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" ...。这样,模拟的视图模型将仅在设计器中创建,而不在运行应用程序时创建。请记住,这种方法要求您的模拟视图模型具有无参数的构造函数。但是上面答案中给出的示例也是如此。
勒内·

2
@René,您的方法要好得多。请添加它作为答案,我将投票给它
dss539,2014年

15

作为Goran接受的答案和Rene的出色评论的混合物。

  • 添加名称空间声明。 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

  • 从代码中引用您的设计时数据上下文。
    <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" ...


1
我很想将其标记为新答案,但是也许我们可以提供其余的细节。
el2iot2

这需要更多的可见性,或者需要将其纳入公认的答案中。这是一个更好的解决方案。
Lauraducky

为什么这样更好?最初,我认为被接受的答案还会在运行时不必要地生成模拟模型,但我对此进行了测试,但实际上并没有。如果不使用资源,则不会创建资源。
保罗

@Paul这实际上是一个优先事项,但是此答案将整个设计时数据上下文保留在一个声明中,而不是将它保留在两个位置。使更改变得更容易
John Stritenberger

1
@JohnStritenberger不仅是首选项,接受的答案还会不必要地一直将资源加载到内存中,而不仅仅是设计人员。
UuDdLrLrSs

4

Karl Shifflett描述了一种对于VS2008和VS2010应该同样有效的方法:

在WPF和Silverlight项目中的Visual Studio 2008 Cider Designer中查看设计时数据

洛朗·布格尼翁(Laurent Bugnion)也有类似的方法,专注于Expression Blend。它可能适用于VS2010,但我尚未确认。

在Microsoft Expression Blend中以设计模式模拟数据


感谢您引起我的注意。我喜欢DesignAndRunTimeDataContext概念。
2010年

1
Karl Shifflett更新了Visual Studio 2010的文章:WPF和Silverlight Designer中的示例数据
totorocat 2010年

1
链接内容的要点实际上应该被编辑为答案,尤其是因为第一个链接现在已失效。
Lauraducky

4

也许您可以选择Visual Studio 2010和Expression Blend 4的新设计时功能。

WPF应用程序框架(WAF)BookLibrary示例应用程序中显示了它的工作方式。请下载.NET4版本。


感谢您的链接。我是否应该查看特定的代码文件或构造以查看方法?(简短的概述将是很棒的)
el2iot2 2010年

看一下BookLibrary.Presentation项目。在该项目中,您可以在“视图”文件夹中找到UserControls使用的“ DesignData”文件夹。
jbe

1
+1。只是看看这个。对于感兴趣的任何人,示例数据视图模型都在XAML中声明,并通过d:DataContext =“ {d:DesignData Source = .. / DesignData / SampleLendToViewModel.xaml}
引用

4

我使用这种方法通过.NET 4.5和Visual Studio 2013生成设计时数据。

我只有一个ViewModel。视图模型具有一个属性IsInDesignMode,该属性指示设计模式是否处于活动状态(请参阅class ViewModelBase)。然后,您可以在视图模型构造函数中设置您的设计时数据(如填充项目控件)。

此外,我不会在视图模型构造函数中加载实际数据,这可能会在运行时导致问题,但是在设计时设置数据应该不是问题。

public abstract class ViewModelBase
{
    public bool IsInDesignMode
    {
        get
        {
            return DesignerProperties.GetIsInDesignMode(new DependencyObject());
        }
    }
}

public class ExampleViewModel : ViewModelBase
{
    public ExampleViewModel()
    {
        if (IsInDesignMode == true)
        {
            LoadDesignTimeData();
        }
    }

    private void LoadDesignTimeData()
    {
        // Load design time data here
    }       
}

4

使用Visual Studio 2017,我一直在尝试遵循所有此类指南和问题,但我仍然面临着一个<ItemsControl>which根本不执行我在DesignFooViewModelfrom 的构造函数中继承的代码的问题FooViewModel。我确认遵循此“方便的” MSDN指南(破坏者:MessageBox调试)中的“未执行”部分。虽然这与原始问题没有直接关系,但我希望它可以节省其他人的时间。

原来我没做错任何事。问题是我的应用程序需要针对x64构建。由于Visual Studio仍在2018年中,所以它是32位进程,并且显然不能为设计器部件旋转64位宿主进程,因此它不能使用我的x64类。真正糟糕的是,在我能想到的任何日志中都找不到错误。

因此,如果您由于在设计时视图模型中看到虚假数据而偶然发现了这个问题(例如:无论将属性设置为否都会<TextBlock Text="{Binding Name}"/>显示Name),则可能是您的x64构建。如果由于依赖关系而无法将构建配置更改为anycpu或x86,请考虑创建一个完全为anycpu且不具有依赖关系(或任何依赖关系)的新项目。因此,您最终会将代码的大部分或全部(初始化部分除外)从“ WPF App”项目拆分为“ C#类库”项目。

对于我正在开发的代码库,我认为这将迫使健康的关注点分离,但要付出一些代码重复的代价,这可能是积极的结果。


3

与评分最高的答案相似,但我认为更好:您可以创建一个静态属性来返回设计数据实例,并直接从XAML引用它,如下所示:

<d:UserControl.DataContext>
    <Binding Source="{x:Static designTimeNamespace:DesignTimeViewModels.MyViewModel}" />
</d:UserControl.DataContext>

这样可以避免使用UserControl.Resources。您的静态属性可以用作工厂,允许您构造非平凡的数据类型-例如,如果您没有默认的ctor,则可以在此处调用工厂或容器以注入适当的依赖项。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.