使用 MVVM 和 WPF 实现真实的可视化

发布于 2024-08-03 01:52:03 字数 411 浏览 6 评论 0原文

我目前需要创建渡轮系统的视觉表示,以显示渡轮在海上的实际位置以及货物的状态。渡轮包含卡车,卡车包含汽车。我需要在甲板上显示实际的卡车及其 xy 位置。当渡轮装载时,卡车的位置会经常更新,因此看起来很生动。我还需要在卡车上展示实际的汽车。卡车、汽车和渡轮也有一些需要显示的状态。因此,我有一个数据的层次结构,我需要以相当现实的方式可视化它。

在 WPF 中实现此类内容的好方法是什么?我是否应该将 MVVM 与一个 TreeView 控件一起使用,并为海运、轮渡、卡车和汽车创建一个 HierarchicalDataTemplates 以及为 TreeView 创建一个 ControlTemplate?或者我应该更好地使用 UserControls 并在代码中组合和更新它们,而不是将数据绑定到 ViewModel 的可观察集合。您有这方面的经验吗?你会怎么做?你能画出类/控制设置的草图吗?

I currently need to create a visual representation of a ferry system that displays the actual ferries their position on the sea and the state of their cargo. The ferries contain trucks and the trucks contain cars. I need to display the actual trucks and their xy postion on the deck. When the ferries are loaded the postions of the trucks are updated frequently so the look animated. Also I need to display the actual cars on the trucks. Trucks, cars and ferries have some states that need to be displayed too. So I have a hierarchical structure of data that I need to visualize in a rather realistic manner.

What would be a good way to implement this kind of stuff in WPF? Should I use MVVM with one TreeView control and create a HierarchicalDataTemplates for sea, ferry, truck and car and a ControlTemplate for the TreeView? Or should I better use UserControls and compose and update them in code instead of databinding to observable collections of the ViewModel. Do you have any experience with this? How would you do this? Could you sketch out class/control setup?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

颜漓半夏 2024-08-10 01:52:03

我建议创建一个“外观”控件,而不是创建用户控件。一般来说,我使用用户控件作为我的外观控件的粘合剂/容器。 Button 类就是无外观控件的一个示例。它包含默认样式,在 Blend 中,您可以随意修改样式。它还支持视觉状态管理器,因此您可以在状态更改时更改演示文稿的外观。您可以将无外观控件的代码隐藏视为迷你 ViewModel。在这里,可以将一些演示内容和您的域类混合在一起。

如果您遵循相同的设计,您可以创建一个 Ferry 外观控件。该控件将具有一组它自己的依赖属性(可能侦听 DP 的 OnChange)。

您的 Ferry 控件可能有一个名为“Trucks”的 ObservableCollection DP。

然后在 Themes\generic.xaml 中,为 Ferry 控件创建默认样式。您的默认样式可能有一个带有 ItemsSource={TemplateBinding Trucks} 的 ItemsControl。 ItemsControl 面板模板可以是您自己的用于排列卡车的自定义面板,也可以使用 Canvas。对于 ItemsControl 项目模板,您将拥有如下内容:

<DataTemplate>
     <mynamespace:TruckControl/>
</DataTemplate>

You Truck 控件,也将是一个具有自己的默认样式的外观控件,并且它的数据上下文已经设置,因此您可以直接执行 {Binding Path=xyz} 。您的卡车控件还可以设置它的 Canvas.Left/Top (如果您选择在之前的项目控件中使用画布......或者如果您为其创建了自定义面板,则可能根本不会设置其位置)或渲染变换以将其放置在正确的 X,Y 位置。您还可以使用卡车模板中的项目控件来渲染汽车,就像在渡轮控件中渲染卡车一样。还可以为 VisualStateManager 创建状态,以使其完全支持 Blend。因此,例如,如果卡车进入“问题状态”,您可以轻松地混合该状态的样式,使其闪烁红色。

我知道这听起来需要消化很多,但最终拥有所有支持 MVVM 模型的可样式控件将使您的生活变得更加轻松 1000000 倍。

我建议研究微软的 silverlight 工具包,以了解如何进行外观简洁的控件等。尝试查看一个简单的控件,例如 DatePicker (http://silverlight.codeplex。 com/SourceControl/changeset/view/25992# )一个警告是忽略 DatePicker.xaml 文件(它只是 generic.xaml 中内容的镜像,如果您只是删除它,不会发生任何不好的情况)。

您应该密切注意的事情是:

1.) 类的属性。这些帮助 Blend 了解如何处理您的控制。

2.) OnApplyTemplate 覆盖。您可以在此处从模板中提取特定元素。这些被称为“零件”,您将在 Blend 中看到零件选项卡。 #1 中的属性可以定义模板中的“部分”以及它们的类型。

3.) 构造函数中的 DefaultStyleKey = typeof(...) 。这告诉 Silverlight 在 generic.xaml 中使用什么默认模板

4.) 查看 Themes\generic.xaml。这是一个特殊的硬编码文件位置,用于存储所有默认模板。搜索 DatePicker 样式,您就会明白了:)

祝您好运!

I'd recommend making a "lookless" control as opposed to making user controls. Generally I use user controls as glue/container for my lookless controls. An example of a lookless control is the Button class. It contains a default style and in Blend, you can modify the style all you like. It also supports the visual state manager so you can change how the presentation looks when states change. You can think of the codebehind of a lookless control as a mini ViewModel. Here it is ok to mix some presentation stuff and your domain classes.

If you follow this same design, you could create a Ferry lookless control. This control would have a set of it's own dependency properties (possibly listening to the OnChange of the DP).

Your Ferry control may have an ObservableCollection DP called "Trucks".

Then in your Themes\generic.xaml, create a default style for your Ferry control. Your default style may have an ItemsControl with an ItemsSource={TemplateBinding Trucks}. The ItemsControl panel template, could be your own custom panel for arranging the Trucks, or maybe you use a Canvas. For the ItemsControl items template, you would have something like this:

<DataTemplate>
     <mynamespace:TruckControl/>
</DataTemplate>

You Truck control, would also be a lookless control with it's own default style, and it's data context will already be set, so you can directly do the {Binding Path=xyz}. Your Truck control could also set it's Canvas.Left/Top (if you chose to use a canvas in the pervious items control..or maybe it doesn't set its position at all if you made a custom panel for it) or a render transform as to put it at the correct X,Y. You could also use the items control in the truck's template to render out the cars in the same fashion you rendered out the trucks in the ferry control. Also its possible to create states for the VisualStateManager as to make it fully Blend supportable. So if a truck goes into a "problem state" you could easily style that state in blend to make it blink red, for instance.

I know it sounds like a lot to digest, but in the end having stylable controls all supporting an MVVM model will make your life 1000000x easier.

I'd suggest studying Microsoft's silverlight toolkit to get a good idea how to do lookless controls and such. Try looking at a simple control, like the DatePicker ( http://silverlight.codeplex.com/SourceControl/changeset/view/25992# ) One caveat is ignore DatePicker.xaml file (it's just a mirror of what gets put in generic.xaml and nothing bad would happen if you just deleted it).

The things you should pay close attention to are:

1.) The attributes on the class. These help Blend know how to deal with your control.

2.) The OnApplyTemplate override. This is where you can pull out specific elements from your template. These are known as "parts" and you will see the parts tab in Blend. The attributes in #1 can define what "parts" are in the template and what type they are expected to be.

3.) The DefaultStyleKey = typeof(...) in the constructor. This tells Silverlight what default template to use in the generic.xaml

4.) Look at Themes\generic.xaml. This is a special hardcoded file location that stores all your default templates. Search for the DatePicker style and you will get the idea :)

Good luck!

一指流沙 2024-08-10 01:52:03

我只是想让你知道我实际上是如何实现它的。事实证明,根本没有必要为此编写自定义控件或用户控件。我所做的只是为汽车、轮船、渡轮、卡车等视图模型编写数据模板。例如,FerryViewModel 的数据模板包含一个具有 Canvas 类型的 ItemsPanel(能够定位卡车)的 ItemsControl 和一个作为 TruckViewModel 的 DataTemplate 的 ItemTemplate。一个非常简单和快速的方法。

I just wanted to let you know, how I actually implemented it. It turned out that it was not necessary at all, to write custom controls or UserControls for this. All I did, was writing datatemplates for the car, ship, ferry, truck etc ViewModels. For example the datatemplate for the FerryViewModel contained an ItemsControl with a ItemsPanel of type Canvas (to be able to position the trucks) and an ItemTemplate that was a DataTemplate for TruckViewModel. A very simple and fast approach.

蓝梦月影 2024-08-10 01:52:03

我建议让一个用户控件处理所有绘图。否则你可能会迷失对象的层次结构。汽车、卡车和渡轮上的人们说,如果添加其他物品也会变得更容易。

如果您的模型是分层的,那么您只需将顶层传递到控件中,然后让控件自行排序。

MVVM 对于现有控件效果很好,但现有 WPF 控件只有在有一个接近您需要的控件时才有效,并且只需进行一些调整即可工作。我想不出 WPF 中的标准控件能够满足您的需求,因此是时候编写一个新控件了。

I'd suggest having one user control handle all the drawing. Otherwise you can get lost the the hierarchy of objects. Also it makes it easier if another item was added, say people in cars, trucks and ferries.

If your model is hierarchical then you can just pass in the top level into the control, and let the control sort itself out.

MVVM works well for existing controls, but existing WPF controls only work if there's a control that's close to what you need, and with a few tweaks would work. I can't think of a standard control in WPF that's close to what you need, so it's time to write a new control.

<逆流佳人身旁 2024-08-10 01:52:03

WPF 与视图模型配合得非常好。如果您可以将代码保留在特别需要的时候,那么您可以更轻松地将用户界面与数据分开。如果数据模型在不同的显示之间不发生变化,它将允许您的用户界面更具可升级性。

WPF works really really well with view models. If you can keep code behind away until specifically needed then you can separate ui from data so much more easily. It will allow your ui's to be some much more upgradeable if the data model doesn't change between different display.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文