我在没有表达式混合的情况下工作,只使用 vs2010 中的 XAML 编辑器。撇开这一点不谈,我越来越发现设计时数据绑定的需求。对于简单的情况,FallbackValue
属性工作得非常好(文本框和文本块等)。但特别是在处理 ItemsControl
等时,确实需要在设计器中显示示例数据,以便您可以调整和调整控件和数据模板,而无需运行可执行文件。
我知道 ObjectDataProvider 允许绑定到类型,因此可以提供用于可视化的设计时数据,但是需要一些技巧才能绑定真实的运行时数据而不浪费资源通过加载加载设计时、虚拟数据和运行时绑定。
我真正想要的是能够让“John”、“Paul”、“George”和“Ringo”在 XAML 设计器中显示为我的 ItemsControl
中的可样式项,但是当应用程序运行时显示真实数据。
我还知道 Blend 允许使用一些奇特的属性来定义设计时绑定数据,而 WPF 在运行时条件下会有效地忽略这些数据。
所以我的问题是:
1。我如何在 Visual Studio XAML 设计器中利用集合和重要数据的设计时绑定,然后顺利地切换到运行时绑定?
2.其他人如何解决设计时与运行时数据问题? 就我而言,我无法轻松地为两者使用相同的数据(就像可以使用数据库查询一样)。
3.它们是我可以用于数据集成 XAML 设计的表达式混合的替代方案吗?(我知道有一些替代方案,但我特别想要一些可以使用并查看绑定示例数据等的东西?)
I am working without expression blend and just using the XAML editor in vs2010. The wisdom of this aside, I am increasingly seeing a need for design-time data binding. For simple cases, the FallbackValue
property works very nicely (Textboxes and TextBlocks, etc). But especially when dealing with ItemsControl
and the like, one really needs sample data to be visible in the designer so that you can adjust and tweak controls and data templates without having to run the executable.
I know that ObjectDataProvider
allows for binding to a type, and thus can provide design-time data for visualizing, but then there is some juggling to allow for the real, run-time data to bind without wasting resources by loading loading both the design time, dummied data and the runtime bindings.
Really what I am wanting is the ability to have, say, "John", "Paul", "George", and "Ringo" show up in the XAML designer as stylable items in my ItemsControl
, but have real data show up when the application runs.
I also know that Blend allows for some fancy attributes that define design time binding data that are effectively ignored by WPF in run-time conditions.
So my questions are:
1. How might I leverage design-time bindings of collections and non-trivial data in the visual studio XAML designer and then swap to runtime bindings smoothly?
2. How have others solved this design-time vs. runtime data problem? In my case, i cannot very easily use the same data for both (as one would be able to with, say, a database query).
3. Are their alternatives to expression blend that i could use for data-integrated XAML design? (I know there are some alternatives, but I specifically want something I can use and see bound sample data, etc?)
发布评论
评论(8)
使用 VS2010,您可以使用设计时属性(适用于 SL 和 WPF)。无论如何,我通常有一个模拟数据源,所以这只是一个问题:
添加名称空间声明
将模拟数据上下文添加到窗口/控件资源
设置设计时数据上下文
效果很好。
Using VS2010 you can use Design-Time attributes (works for both SL and WPF). I usually have a mock data-source anyway so it's just a matter of:
Adding the namespace declaration
Adding the mock data context to window/control resources
Setting design-time data context
Works well enough.
作为戈兰接受的答案和雷内优秀评论的结合体。
添加命名空间声明。
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
从代码中引用您的设计时数据上下文。
As an amalgam of Goran's accepted answer and Rene's excellent comment.
Add the namespace declaration.
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Reference your design time data context from code.
<Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" ...
我使用这种方法通过 .NET 4.5 和 Visual Studio 2013 生成设计时数据。
我只有一个 ViewModel。
视图模型有一个属性
IsInDesignMode
,它告诉设计模式是否处于活动状态(请参阅类ViewModelBase
)。然后,您可以在视图模型构造函数中设置设计时数据(例如填充项目控件)。
此外,我不会在视图模型构造函数中加载真实数据,这可能会导致运行时出现问题,但为设计时设置数据应该不是问题。
I use this approach for generating design time data with .NET 4.5 and Visual Studio 2013.
I have just one ViewModel.
The view model has a property
IsInDesignMode
which tells whether design mode is active or not (see classViewModelBase
).Then you can set up your design time data (like filling an items control) in the view models constructor.
Besides, I would not load real data in the view models constructor, this may lead to issues at runtime, but setting up data for design time should not be a problem.
Karl Shifflett 描述了一种应该同样适用于 VS2008 和 VS2010 的方法:
在 WPF 和 Silverlight 项目中的 Visual Studio 2008 Cider Designer 中查看设计时数据
Laurent Bugnion 有类似的方法专注于表达混合。它可能适用于VS2010,但我还没有证实这一点。
在 Microsoft Expression Blend 的设计模式下模拟数据
Karl Shifflett describes an approach that ought to work equally well for VS2008 and VS2010:
Viewing Design Time Data in Visual Studio 2008 Cider Designer in WPF and Silverlight Projects
Laurent Bugnion has a similar approach that focuses on Expression Blend. It might work for VS2010, but I haven't confirmed this yet.
Simulating data in design mode in Microsoft Expression Blend
也许 Visual Studio 2010 和 Expression Blend 4 的新设计时功能是您的一个选择。
其工作原理如 WPF 应用程序框架 (WAF)。请下载.NET4版本。
Maybe the new design-time features of Visual Studio 2010 and Expression Blend 4 are an option for you.
How it works is shown in the BookLibrary sample application of the WPF Application Framework (WAF). Please download the .NET4 version.
与最受好评的答案类似,但我认为更好:您可以创建一个静态属性来返回设计数据的实例并直接从 XAML 引用它,如下所示:
这避免了使用
UserControl.Resources
。您的静态属性可以充当工厂,允许您构造重要的数据类型 - 例如,如果您没有默认构造函数,则可以在此处调用工厂或容器以注入适当的依赖项。Similar to the top rated answer, but better in my opinion: You can create a static property to return an instance of design data and reference it directly from XAML like so:
This avoids the need to use
UserControl.Resources
. Your static property can function as a factory allowing you to construct non-trivial data types - for example if you do not have a default ctor, you can call a factory or container here to inject in appropriate dependencies.使用 Visual Studio 2017,我一直在尝试遵循所有指南和诸如此类的问题,但我仍然面临
它根本不执行我在构造函数中的代码DesignFooViewModel
继承自FooViewModel
。我确认了此 "handy" MSDN 指南之后的“未执行”部分 (剧透:MessageBox
调试)。虽然这与原来的问题没有直接关系,但我希望它能为其他人节省很多时间。事实证明我没有做错什么。问题是我的应用程序需要针对 x64 构建。由于 Visual Studio 在 2018 年仍然是 32 位进程,并且显然无法旋转 64-设计器部分的位主机进程无法使用我的 x64 类。真正糟糕的是,在我能想到的任何日志中都找不到错误。
因此,如果您偶然发现这个问题,因为您在设计时视图模型中看到虚假数据(例如:
显示Name
无论您将该属性设置为什么),原因都可能是您的 x64 版本。如果由于依赖关系而无法将构建配置更改为anycpu或x86,请考虑创建一个完全是anycpu并且没有依赖关系(或任何依赖关系)的新项目。因此,您最终将代码的大部分或全部(除了初始化部分)从“WPF 应用程序”项目分离到“C# 类库”项目中。对于我正在开发的代码库,我认为这将迫使健康的关注点分离,但代价是一些代码重复,这可能是净积极的事情。
Using Visual Studio 2017 I have been trying to follow all of the guides and questions such as this and I was still facing a
<ItemsControl>
which simply did not execute the code I had inside the constructor of aDesignFooViewModel
which inherits fromFooViewModel
. I confirmed the "did not execute" part following this "handy" MSDN guide (spoiler:MessageBox
debugging). While this is not directly related to the original question, I hope it will save others a lot of time.Turns out I was doing nothing wrong. The issue was that my application needs to be built for x64. As the Visual Studio is still in 2018 a 32-bit process and apparently cannot spin a 64-bit host process for the designer part it cannot use my x64 classes. The really bad thing is that there are no errors to be found in any log I could think of.
So if you stumble upon this question because you are seeing bogus data in with your design time view model (for example:
<TextBlock Text="{Binding Name}"/>
shows upName
no matter you set the property to) the cause is likely to be your x64 build. If you are unable to change your build configuration to anycpu or x86 because of dependencies, consider creating a new project which is fully anycpu and does not have the dependencies (or any dependencies). So you end up splitting most or all but the initialization parts of the code away from your "WPF App" project into a "C# class library" project.For the codebase I am working on I think this will force healthy separation of concerns at the cost of some code duplication which is probably net positive thing.
我喜欢 jbe 的建议,特别是看看他们如何在 WAF 框架示例应用程序中执行此操作 - 他们在
DesignData
文件夹中使用单独的模拟/示例视图模型,然后在 XAML 中添加如下行:(其中
dd
指向MockHomeViewModel
所在的.DesignData
命名空间)它很好且简单(我喜欢!),您可以从真实的虚拟机,只提供虚拟数据。它将事情分开,因为您不需要使用任何仅设计时的代码来污染您的真实虚拟机。我明白对于使用 IOC 等的大型项目来说,情况可能看起来完全不同,但对于小型项目来说,它效果很好。
但正如 Joonas 指出的那样,它似乎不适用于 VS2017 中的 x64 版本,而 VS2019 似乎仍然如此(我正在使用 V2019 16.6 社区版)。一开始工作并不麻烦,但在进行更改(或者通常情况下,进行多次更改!)后突然停止工作可能会导致一些头痛。
对于任何尝试它的人,我建议创建一个新的简单 WPF 项目(例如一个视图、一个视图模型、一个模拟虚拟机)并使用它;让它工作然后打破它。我发现有时,再多的解决方案清理和重建也无法修复它,唯一有效的就是关闭 VS 并重新启动,突然我的设计时数据又回来了!
I liked jbe's suggestion, specifically to look at how they do it in the WAF framework sample apps - they use separate mock/sample view models in a
DesignData
folder and then have a line like this in the XAML:(where
dd
points to the.DesignData
namespace whereMockHomeViewModel
lives)It's nice and simple (which I like!) and you can inherit from the real VMs and just provide dummy data. It keeps things separate as you don't need to pollute your real VMs with any design time only code. I appreciate things might look quite different for a large project utilising IOCs etc but for small projects it works well.
But as joonas pointed out, it seems not to work with x64 builds in VS2017 and this still seems to be the case with VS2019 (I'm using V2019 16.6 Community edition). It's not fiddly to get working to start off with but can cause some head scratching when after making a change (or as is usually the case, several changes!) it suddenly stops working.
For anybody trying it, I would recommend creating a new simple WPF project (say one view, one view model, one mock vm) and play around with it; get it working and then break it. I found sometimes, no amount of solution cleans and rebuilds would fix it, the only thing that worked was closing VS down and restarting, and suddenly my design time data came back!