WPF中虚拟设计时数据有哪些方法可用?

时间:2009-12-11 18:25:08

标签: wpf data-binding xaml designer design-time

我正在使用没有表达式混合,只使用vs2010中的XAML编辑器。除此之外,我越来越多地看到了对设计时数据绑定的需求。对于简单的情况,FallbackValue属性非常好(Textboxes和TextBlocks等)。但特别是在处理ItemsControl之类的时候,确实需要在设计器中显示样本数据,以便您可以调整和调整控件和数据模板,而无需运行可执行文件。

我知道ObjectDataProvider允许绑定到一个类型,因此可以提供可视化的设计时数据,但是有一些杂耍可以让真实的运行时数据绑定而不会浪费资源通过加载加载设计时间,dummied数据和运行时绑定。

我真正想要的是能够让“John”,“Paul”,“George”和“Ringo”在我的ItemsControl中作为可设置项目出现在XAML设计师中,但是在应用程序运行时显示实际数据。

我也知道Blend允许一些花哨的属性来定义WPF在运行时条件下有效忽略的设计时绑定数据。

所以我的问题是:

1。我如何利用visual studio XAML设计器中的集合和非平凡数据的设计时绑定,然后顺利地交换到运行时绑定?

2。其他人如何解决这个设计时与运行时数据问题?在我的情况下,我不能很容易地为两者使用相同的数据(例如,数据库查询可以使用相同的数据)。 p>

第3。他们可以用于数据集成XAML设计的表达混合替换吗?(我知道有一些替代方案,但我特别想要一些我可以使用的东西,看看绑定的样本数据等?)

8 个答案:

答案 0 :(得分:117)

使用VS2010,您可以使用Design-Time attributes(适用于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}}" ...
    

运作良好。

答案 1 :(得分:9)

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

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

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

答案 2 :(得分:4)

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

Viewing Design Time Data in Visual Studio 2008 Cider Designer in WPF and Silverlight Projects

Laurent Bugnion有类似的方法专注于Expression Blend。 可能适用于VS2010,但我还没有确认。

Simulating data in design mode in Microsoft Expression Blend

答案 3 :(得分:4)

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

工作原理显示在 WPF Application Framework (WAF) BookLibrary 示例应用程序中。请下载.NET4版本。

答案 4 :(得分:3)

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

我只有一个ViewModel。 视图模型具有属性IsInDesignMode,用于指示设计模式是否处于活动状态(请参阅类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
    }       
}

答案 5 :(得分:3)

使用Visual Studio 2017,我一直在尝试遵循所有此类指南和问题,但我仍然面临着<ItemsControl>的问题,该问题根本没有执行我在{{1 }}继承自DesignFooViewModel。在此"handy" MSDN guide(调试器:FooViewModel调试)之后,我确认了“未执行”部分。虽然这与原始问题没有直接关系,但我希望它可以为其他人节省很多时间。

原来我没做错任何事。问题是我的应用程序需要针对x64构建。由于Visual Studio is still in 2018 a 32-bit process显然无法为设计器部件旋转64位主机进程,因此它无法使用我的x64类。真正糟糕的是,在我能想到的任何日志中都找不到错误。

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

对于我正在研究的代码库,我认为这将迫使健康的关注点分离,但要花一些代码重复的代价,这可能是纯正的事情。

答案 6 :(得分:1)

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

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

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

答案 7 :(得分:0)

我喜欢 jbe 的建议,特别是看看他们如何在 WAF 框架示例应用程序中做到这一点 - 他们在 DesignData 文件夹中使用单独的模拟/示例视图模型,然后在 XAML 中有这样一行:

mc:Ignorable="d" 
d:DataContext="{d:DesignInstance dd:MockHomeViewModel, IsDesignTimeCreatable=True}"

(其中 dd 指向 .DesignData 所在的 MockHomeViewModel 命名空间)

它既漂亮又简单(我喜欢!),您可以从真实的 VM 继承并只提供虚拟数据。它使事情保持独立,因为您不需要使用任何仅设计时的代码来污染您的真实虚拟机。我很欣赏使用 IOC 等的大型项目的情况可能会大不相同,但对于小型项目,它运行良好。

但正如 joonas 指出的那样,它似乎不适用于 VS2017 中的 x64 构建,而且 VS2019 似乎仍然如此(我使用的是 V2019 16.6 社区版)。开始工作并不繁琐,但在进行更改(或通常情况下,多次更改!)后突然停止工作时可能会引起一些头疼。

对于任何尝试它的人,我建议创建一个新的简单 WPF 项目(比如一个视图、一个视图模型、一个模拟虚拟机)并使用它;让它工作,然后打破它。我发现有时,没有多少解决方案清理和重建可以修复它,唯一有效的是关闭 VS 并重新启动,然后我的设计时数据突然回来了!