简体   繁体   中英

What design pattern should be used in C# with WPF for dynamically “changing object's classes” via a user interface?

I'm currently working on an C# WPF application that allows you to create a graph (ie a bunch of vertices that are connected via edges) and then use this graph as a pattern to find it in a bunch of other (larger) graphs ("host" graphs). Each graph element has at least a type and a label.

The pattern graph elements (edges and vertices) can have different "restriction types".

A vertex for example can have the restrictions "This vertex' label must be 'Vertex A'" or "This vertex' type must be in the set {Type A, Type B, Type H}".

For edges, the restriction types are a bit more difficult. An edge can be restricted to either be a "simple" edge or a "path" edge. A path edge between two vertices in a pattern graph can be considered a placeholder that allows you to find multiple edges (and vertices) between the two vertices in a host graph. In contrast, a simple edge allows you to find only one edge (and no additional vertices) in a host graph.

If an edge has a path restriction (instead of a normal edge restriction) it has some additional properties like minimum path length or allowed vertex types that are allowed on the path.

The type restriction structure can be seen in this UML class diagram: 图片1

~~~

Now from the UI point of view: A user should be able to configure if a edge has a path restriction. If it has, the neccessary additional controls (TextBoxes, ListBoxes etc.) for the additional settings should automatically appear. Changes in all controls should automatically be reflected in the data structure.

Here's what the user interface should behave like when changing settings of a selected edge: image2 (Actually, on the right side there should also be a scroll bar on the right side that allows you to scroll down and configure also the allowed edge types on the path. Also ignore the vertex and edge overlap settings for now.)

~~~

Finally, my questions boil down to:

How do you implement such a dynamic object class change while maintaining WPF's data binding elegancy? (With dynamic object class change I mean that by clicking on the "Consider this edge as a path" checkbox the selected edge will get a different restriction type.)

Do I really have to create an old-school event listener that gets triggered when changing the value of the "Consider this edge as a path" checkbox and use it to update the visibility of the other sidebar controls "manually"?

Would it help in any way if I changed my restriction class structure somehow?

Okay, I don't really speak design patterns, so I'm not answering in those terms. I do speak WPF though, and design patterns usually turn out to be something I'd already done but didn't know what it was called.

WPF doesn't really care what type anything is. If you're displaying it using a DataTemplate in a ContentControl of some sort you can have one for every type the object might actually be that needs special treatment and WPF will take care of that for you. A DataTemplateSelector might be a good idea for more complicated logic for choosing the UI pieces for a given type, which in my experience tends to happen in many supposedly simple scenarios that turn out not to be. The disadvantage is that a DataTemplateSelector has to know about all your data types and templates in order to be able to choose between them.

This only really works for the side panel though, the rendering of the actual graph probably needs to be done in a more holistic manner and is, I would say, a completely different problem.

The design pattern you're after is probably MVVM . It looks like you're currently attaching your UI to your model directly with no view model in between. Sometimes you can get away with this, sometimes not.

You could write a value converter applied to the binding of the IsChecked property that converts a boolean into the correct instance of a restriction class and back. As the checkbox state changes, a different instance is created and assigned into your model. This will be reflected in the UI with the choice of data template.

It's likely to be more complicated than that, for example if you want to preserve values between the changes of state. That is where you would want to introduce a view model to sit in between the UI and the model. The view model closely reflects the UI and has a corresponding boolean property, and when that changes you can change the model accordingly.

Either way, there should be no reason to hook onto events on controls: try and handle this all in view models.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM