C# MVVM TreeView TwoWay-Binding of hierarchical data - c#

I googled for an answer to this for more than two weeks now. This usually means either I am blind or the idea is absurd. Anyways:
In a middle-sized, quite flexible project I'm storing configuration data in a hierarchical structure in the like of this one:
Configuration (collection)
Audio (class)
BaseDir (struct)
PlayMode (enum)
Input (class)
CalibrateOnConnect (bool)
KnownDevices (collection)
... (class)
...
UseDevice (integer)
Playlist (collection)
FirstAudio (class)
Path (string)
Repeat (integer)
...
I already managed to display these in a TreeView in a MVVM pattern. Since I can't exactly tell which options will be added in future, I used a generic approach, creating ViewModels for class, ienumerable, my custom structs and the basic value types (string, bool, enum, ...).
In my XAML these have their corresponding (Hierarchical)DataTemplates, e.g. with a CheckBox for booleans or a textblock for general value types.
Each ViewModel instance has a field to store the data of the underlying Model.
I manage to edit these values in the View and via TwoWay-Binding also in the ViewModel.
But what makes my head hurt is how to update this data in the Model.
Since I create the hierarchical ViewModel structure through reflection, the parents do not have get/set properties corresponding to the field names / indexers / ... of the equivalent configuration class / collection. Though each ViewModel instance knows the field/property name of the parent's model's data structure it was created from and knows its parent ViewModel instance, too (but not its parent Model instance).
Every attempt to solve this problem via Commands or by calling some parent's update function made a knot into my brain.
Isn't there a simple way to achieve this via regular binding techniques?
Would it be better if I created ViewModels for each configuration (sub)class I'm using?
Hint: Each ViewModel instance knows its field / property name in the parent's model's data structure.

Reading through the comments I'd argue that a view model should be tightly coupled to the model that it is trying to represent. Having a dynamic view model is also very hard to test.
However, if you really wanted to try to get around this, you could consider using a DynamicObject which allows you to get/set properties on the instance in a completely generic fashion. With DynamicObjects you are then given hooks that are called when a property is either set or got, this would enable you (for example) to raise NotifyPropertyChange events for a given dynamic property.

Related

WPF custom control throwing an event for the GUI to handle [duplicate]

When should I use dependency properties in WPF?
They are static, so we save a lot on memory, compared to using .NET properties.
Other gains of using dependency properties over .NET properties are:
1) no need to check thread access
2) prompt a containing element to be rendered
etc...
So it seems I should ALWAYS use dependency properties in my projects where I use WPF?
Maybe for some trivial properties of helper classes here and there I could
get away with .NET properties...
Dependency Property is a broad concept to explain which might take couple of pages to write. So just to answer your main question, Dependency property is used where
You know the property is going to be the binding target i.e you are creating a user control/custom control and want property that should be binding driven.
You want automatic property change notifications (coerse and validation also).
We want value inheritance in styles,themes, parent or default value.
There is not need to create the properties on Model or ViewModel layer as dependency properties most of the time as that is not going to help much on memory saving front as most of the properties we define in model/VM will have values per instance as they will be constantly changing. Resolving Dependency property value is a burden in itself so making property dependency unnecessarily is not advisable.
Thanks
The main reason to create DependencyProperty is when you write you own WPF control.
DependencyProperties can be used as binding source and target, and can be animated.
The properties of all framework's controls are implemented as DependencyProperty, that why you can make powerful data binding in XAML.
However in most situation, like in with the MVVM pattern, you don't need dependency properties, INotifyPropertyChanged is enough.
The main difference is, that the value of a normal .NET property is read directly from a private member in your class, whereas the value of a DependencyProperty is resolved dynamically when calling the GetValue() method that is inherited from DependencyObject.
When you set a value of a dependency property it is not stored in a field of your object, but in a dictionary of keys and values provided by the base class DependencyObject. The key of an entry is the name of the property and the value is the value you want to set.
The advantages of dependency properties are
Reduced memory footprint:
It's a huge dissipation to store a field for each property when you think that over 90% of the properties of a UI control typically stay at its initial values. Dependency properties solve these problems by only store modified properties in the instance. The default values are stored once within the dependency property.
Value inheritance:
When you access a dependency property the value is resolved by using a value resolution strategy. If no local value is set, the dependency property navigates up the logical tree until it finds a value. When you set the FontSize on the root element it applies to all textblocks below except you override the value.
Change notification:
Dependency properties have a built-in change notification mechanism. By registering a callback in the property metadata you get notified, when the value of the property has been changed. This is also used by the databinding.
check the below url for more details about the magic behid it
dependency properties in WPF
CLR Property vs. Dependency Property
A CLR property reads directly from the private member of the class. The Get() and Set() methods of the class retrieve and store the values of the property.
Whereas when you set a value of a Dependency Property it is not stored in a field of your object, but in a dictionary of keys and values provided by the base class DependencyObject. The key of an entry is the name of the property and the value is the value you want to set.
Advantages of a Dependency Property
Less memory consumption
The Dependency Property stores the property only when it is altered or modified. Hence a huge amount of memory for fields are free.
Property value inheritance
It means that if no value is set for the property then it will return to the inheritance tree up to where it gets the value.
Change notification and Data Bindings
Whenever a property changes its value it provides notification in the Dependency Property using INotifyPropertyChange and also helps in data binding.
Participation in animation, styles and templates
A Dependency Property can animate, set styles using style setters and even provide templates for the control.
CallBacks
Whenever a property is changed you can have a callback invoked.
Resources
You can define a Resource for the definition of a Dependency Property in XAML.
Overriding Metadata
You can define certain behaviours of a Dependency Property using PropertyMetaData. Thus, overriding a metadata from a derived property will not require you to redefine or re-implement the entire property definition.
Perhaps you should take another look at the Dependency Properties Overview page at MSDN.
Personally, I would only ever create a DependencyProperty when I really need to. For the most part, I use normal CLR properties in data type and view model classes to bind to... this is absolutely fine, as long as I implement the INotifyPropertyChanged interface.
So for all of my usual data bindings, I use normal CLR properties. I only declare a Dependency Property in order to provide some added functionality in a UserControl.
Dependency properties are used when you want data binding in a UserControl, and is the standard method of data binding for the WPF Framework controls. DPs have slightly better binding performance, and everything is provided to you when inside a UserControl to implement them.
Otherwise, you typically use INotifyPropertyChanged for binding elsewhere, since it's easier to implement in stand-alone classes and has less overhead. As far as your original assumptions:
There is a local instance of your variable, you definitely do not save any overhead over a property since there is significant data binding logic built-in.
They must be accessed on the main thread.

(Nested) ViewModel for primitive (value) datatypes (numbers, enums)

I'm working on a wpf application. I use the mvvm pattern.
I have several usercontrols and I want them to have their own viewmodels because I want to reuse these usercontrols in different views without implementing the same (uc-specific) logic in a "super"-viewmodel again and again.
So I have different main viewmodels for every view and each of these viewmodels creates an instance of my subviewmodel, passing a certain property of my model in the constructor of the subviewmodel.
As long as this property is a reference type (class, List<>,...), the changes I make in the subviewmodel/usercontrol are made directly to the model itsself (since it's a reference type).
But when the subviewmodel is for a primitive type, like an integer or an enum, this does not happen because the value is only a copy of the value an when I edit this value I edit the copy and not the value of the model, of course.
How can I solve this? What can I do to get the changed value back to my model?
I do not want to implement a "viewmodel-communication-service" because this seems to be too "big" for the small app I'm working on. For the same reason I also don't want to use any third party components.
In the main viewmodel, should I listen to the propertychanged event of the subviewmodel (and check if the changed property is my primitive property (check its name) and write the new value back to the model)? Hmm that should work but I'm no big fan of using events in scenarios like this since they arrive asynchronously.
Or is it possible to somehow pass the primitive type to the subviewmodel as a ref value (like using ref for method parameters)?

Design practice for container class with multiple collections which reference each other

I'm trying to design a class structure with the following:
Container class which holds all the items.
Item collection class which is inside the Container, where each Item has a unique ID and some other data, including a reference to an ItemStyle.
ItemStyle collection class which is inside the Container, where each ItemStyle represents a common style of items and also the relationship to other styles.
Relationships can be "Attaches To" where a style has a list of other styles it can attach to, and "Attachments" which is the inverse of that. If a style can "Attach To" another style, then the other style should be able to produce the first style as one of its "Attachments".
The container manages the Items and the ItemStyles. I use unique IDs for everything because I want to be able to serialize to and from XML.
However I keep running into logical problems such as I am trying to deserialize an ItemStyle from XML, but of course it can't generate references to the item IDs that it reads since only the Container itself has access to the other items.
Another issue is I want these classes to be independent to the point where if I have a reference to an Item, I can invoke a list of compatible items such as calling "Item.Attachments" or "Item.AttachesTo". This of course all needs to be calculated by the Container since it is the only class to be able to access both the ItemStyles and the Item collections.
So I'm running into a solution where I am going to have to give each Item and ItemStyle a reference to the Container so they can perform their own lookups and determine their relationship with other items. This seems like bad encapsulation and bad OOP practice, but I can't think of any other way.
I'm trying to compare my code to how a ListView works as an example. A ListView has a ListViewItemCollection and ListViewItems. In user code when you can create a new ListViewItem and when you add it to a ListViewItemCollection, it automatically now has a reference to its parent ListView. When looking at the metadata it shows the ListView reference as only having a getter. Can I assume that it uses an internal set?
Should following the ListView model of owner/item relationship work with my classes?
Looking at a tight coupling between all classes involved, I don't think that having a reference to the parent (Container) would be a bad idea. There are many models that rely on having parent reference (typical reason could be to ensure a single parent but other reasons such as validations etc can be a cause) - one of the way to model is to have non-public constructor and construct objects via factory methods. Another way of modelling is to have public constructor but have internal setter to set the parent reference. Whenever child is added to the parent's collection object, the reference is set.
I would prefer the later approach. However, one of the thing that I would do is to avoid direct coupling with Container. Rather, I will introduce IContainer interface that will abstract look-ups needed in children and children (Item/ItemStyle) will know only about IContainer interface.
Yet another reasonable design would be to raise events from children when they want to do look-ups. These will be internal events that will be handled by container when the children are added to it.
Yet another approach would be to have a loose model. Essentially, Item can maintain its own ItemStyle references. Whenever needed, Container can build ItemStyle collection by implementing visitor pattern.

Rule-based available values for a property within model

I have a question regarding where to put available values of a specific property within a model class. Imagine you have a model class that has two properties Family and Series where the possible values of the Series property depends on the value of the Family property.
The business logic contains a set of rules that defines which Series values are available due to the value specified by the Family property. The model itself should always have a valid state, that means if the value of the Family property changes and the available values of the Series property also change, the value of the Series property itself must be changed to one of the available values to fit the valid state.
My intention is to display the available values within a ComboBox for both the Family property and the Series property. But at the moment I'm not sure whether to put the available values of the Series property
into the ViewModel,
into the Model,
or to introduce a separate layer between ViewModel and Model which covers data validation and the functionality of providing available values for specific properties within the model (that acts as plain data container).
I tend to use the second or third approach (I prefer the third approach) because of the directly dependent values within the model. This example in fact is very simple. The real problem covers about nearly 200 values where the available values of a single property can depend on up to 5 or 10 other properties.
In addition, the dependent values may not be located within a single model class and the concerning model classes do not know each other. So it is possible that the values that are required to get the available values for a property of a model class can be located within two or more other model classes.
What do you think is the best approach? Is there another (better) way to solve this I have not mention above?
Thanks,
Oliver
Since you already stated that the Model classes do not know each other, you certainly should not create dependencies just for the purpose of validation/aggregation/filtering (or whatever you might call it) on such a deep layer.
Your requirements generally fit the concerns of a ViewModel which cover value prepation among other things. On the other hand, you don't want to rely on a ViewModel doing that validation given that you model always has to be in a valid state. Just imagine you might add another client later that uses your Model data but can't use the ViewModels.
Therefore, an additional "layer" or service might be the best option in my opinion.

Using MVVM with CollectionViewSource

I'm trying to use CollectionViewSource to display some data, and all the examples/tutorials I've seen have a custom class built, which they use in another class, which inherits from ObservableCollection. I'm new to both using CollectionViewSource and this is only my third implementation of MVVM, so I might misunderstand the programming pattern, but my question is:
where do I put the ObservableCollection class and/or custom class?
I feel like they should go in the Model, but then I'm not sure what gets bound to the View. Do I just build these as external classes, and then reference them in Model/ViewModel?
Any help is appreciated
Firstly, I would say that there is no need to inherit from ObservableCollection<T> unless you are adding functionality to it which I have rarely, if ever, actually needed to do.
In most cases I create ViewModel properties of type ObservableCollection<T> and then populate them from the Model whenever I load the data. This has the advantage that the Model does not need to use ObservableCollection<T> (it can be any IEnumerable<T>) and it means that later when I (almost inevitably) want to wrap whatever I'm getting back from the Model in another instance-specific view model I am only obliged to change my existing view model classes.
Once you have a property on your view model you can simply bind your CollectionViewSource to that property and it will do everything from there. It's worth noting that the CollectionViewSource doesn't actually care about the type of the property, so you can expose your collection to the View as an ICollection<T>, IEnumerable<T> or (I believe) even as an object and the CollectionViewSource will still treat it the same as if it is exposed as an ObservableCollection<T>.
Sorry for the slightly rambling answer. The concise version would be "it depends on the situation" but I tend to follow this general approach in most cases.

Categories

Resources