WPF Binding data class programmatically - wpf

I have a data object (lets call it employee) who has many get/set methods to manipulate/store various parameters.
This object is a singleton object used and referenced in many places in the WPF app.
I am now building a view using Microsoft Expression Blend and would like to bind using Blend cool interface every of my control to the various method of my data object.
When I try it, it will always create a static version of my employee data class.
Is there a way to benefit from the nice user interface of blend to bind parameters and then afterward in the code, set my singleton employee data class as the reference to use?
best,

You can tell blend to use a given type for design-time bindings, and then use whatever you like at runtime. The syntax looks like this:
d:DataContext="{d:DesignInstance data:Employee}"
Read here for more info.

Related

How do you get the WPF / XAML designer to work with custom classes with dependencies?

I'm using a custom class to perform validation in a WPF app and have defined a class which inherits from ValidationRule. The class has a dependancy which I would like AutoFac to inject at runtime, but the Visual Studio 2010 XAML designer needs a parameterless constructor in order to work.
It seems the only solution is to create a DependencyProperty for the dependency and bind it in XAML, but that means the dependency is publicly accessible and mutable, neither of which I want.
Is there any way to pass a dependency in to a class you intend to use in XAML which will do all of the following?
Not break the designer.
Keep the dependency private.
Make sure the dependency is set before the class is used.
How badly do you want to do it?
The features in XAML 2009 provide the following elements which could help you:
x:Arguments would allow you to pass an argument to the constructor. Can this argument be somehow bound to a property of your view model?
x:FactoryMethod allows you to specify the method which creates the object. I assume this can be a method of your window or usercontrol, which would have access to your dependency container.
But here's the problem: XAML 2009 can only be loaded at runtime via a XAML Reader, and can not be compiled. (See Can't get the new 2009 XAML primitives working, why?).
So global static objects (eurgh) might still be the less painful solution.
Later Edit: I reread your question, and realised you had put "Not break the designer" as one of you requirements. This excludes XAML 2009 from the possible solutions.
This is an excellent question. I used techniques demosontrated here to keep the designer working: http://jonas.follesoe.no/2008/07/24/youcard-re-visited-implementing-dependency-injection-in-silverlight/
It not only keeps it working but you can use the technique to put mocks into the designer. Very handy.

viewmodel have to be public. How should I deal with that?

Pretty much it summarizes my problem here:
Double check - does it ever make sense to have internal viewmodel class?
I have controls.DLL and I'd like to keep this custom control bindings and viewmodel's internal. However, this doesn't seem to be possible.
How do you get around that? The only way I see it - don't use bindings..
Why do you have a view model for a custom control? I assume you're assigning the view model object to the DataContext property, but this is almost always a mistake: the DataContext should be available to consumers to use and abuse as they please. Stated another way, what happens if a consumer of your custom control explicitly sets the DataContext? It sounds like your control will stop working and throw a bunch of xaml binding errors.
A custom control is inherently lookless. There is no model or view model, just a view. That view is the .cs file. You supply a default look via your themes/generic.xaml file, but consumers should be able to supply their own template. If you're tying them to a view model, they also need to know how to create a view model instance and all of its dependencies. You've just created highly coupled code. DI containers can loosen the coupling, but that just downgrades the relationship between classes from "coupled" to "related". I say, why do consumers even need to know that information?
A better approach is to provide all of the properties for your control as dependency properties. Then your generic.xaml can provide a control template that uses the more efficient TemplateBinding to bind properties/objects to your control. If you need to populate these dependency properties from a business object, expose another dependency property of type IBusinessObject and set the derived values in that object's PropertyMetaData changed handler. If your IBusinessObject type contains a property which is yet another class which implements INotifyPropertyChanged, you should probably (1) rethink your object graph or (2) create a Bnding object in code using the subclass.
I think following all of the above advice will eliminate the problem about which you're concerned plus the other problems as well. Leave the view models to the UserControls. And yes, this is why custom controls are a MASSIVE headache. Doing them right is fairly involved.
Try protected internal. I suppose this should work. Although I don't think its good idea to have the ViewModel not public at all, cause one of the purposes of it is to be able to define several Views against the same ViewModel, which may come from different assemblies.

How to handle bindable application wide variables in a WPF MVVM application?

I am writing a fairly large scale WPF desktop application using the MVVM pattern. I have been stuck for a while on getting my common properties to update in a View other than the one that updated it.
I have a RibbonWindow MainView that contains a ContentControl that displays the remaining Views one at a time dependant on the user's selection. I have a BaseViewModel class that all the ViewModels extend. Among other things, this class exposes the INotifyPropertyChanged interface and contains a static property of type CommonDataStore. This class also implements the INotifyPropertyChanged interface and contains the properties that are to be available to every ViewModel.
Now, although I can access and successfully update the CommonDataStore properties from any ViewModel, the problem is that the WPF Framework will only notify properties that have changed in the current View. Therefore, although the common values have been updated in other ViewModels, their associated Views do not get updated.
One example from my application is the login screen: As the user logs in, my LogInView updates with the new information (ie. full name) from the database, but the user details in the MainView do not.
After reading a few other posts, I also tried implementing the CommonDataStore class as a Singleton, but that didn't help. I could also just pass a reference to this common data object to the constructor of each ViewModel from the MainViewModel, but I'm not sure if this is the right way to go.
I have also discovered that in WPF, static properties are treated a bit like constant values. It seems that they just read the value once.
So anyway it's clear, my attempts have all failed. I was wondering what the standard way of doing this was? In particular, I need to be able to bind to the common properties and have all of my ViewModels and Views update when any common value is changed. Any help would be greatly appreciated. Many thanks in advance.
Edit >> Really? No one uses application wide variables in an MVVM WPF application?
I have now removed the static part of the Common property declaration and am simply passing a copy into each ViewModel individually. This seems to work, but I'd really like to know how others approach this situation. Please answer by simply letting me know how you organise this application wide data.
I have done something similar to what you describe last. I have class called SecurityContext that holds some of the application-wide data. One instance is created when the application starts up and then that instance is passed into the constructors of all the ViewModels through dependency-injection. I have a base class for ViewModels which exposes that object through a regular instance property (implementing INotifyPropertyChanged).
Have you looked into implementing the Observer Pattern? We have done so with IObservable and IObserver. This describes the "IObservable/IObserver Development Model" as follows:
The IObservable/IObserver development model provides an alternative to using input and output adapters as the producer and consumer of event sources and sinks. This model is based on the IObservable/IObserver design pattern in which an observer is any object that wishes to be notified when the state of another object changes, and an observable is any object whose state may be of interest, and in whom another object may register an interest. For example, in a publication-subscription application, the observable is the publisher, and the observer is the subscriber object. For more information, see Exploring the Observer Design Pattern on MSDN.

Any way to use interfaces with wpf HierarchicalDataTemplate

Hi I am using an interface IFooNode, which is part of a tree.
I wanted to display this tree in a TreeView using a HierarchicalDataTemplate.
This however does not work due to the interface.
I see two ways around that neither are what I would call "nice"
Find out what type really implements IFooNode (let's call it FooNode...), then find the assembly defining FooNode, add a Reference to that assembly and create a HierarchicalDataTemplate for FooNode (hoping the Implementating class never changes...)
Write a class MyCoolIFooNodeWrapperForWpf that wraps IFooNode, do not bind to the tree, but fill a list of MyCoolIFooNodeWrapperForWpf from the tree root and create a HierarchicalDataTemplate for MyCoolIFooNodeWrapperForWpf.
Can I somehow always apply a HierarchicalDataTemplate, no matter what type the data is (This I think would be the lesser evil...)
Any other Ideas?
You can use ItemTemplateSelector. In the selector's code you can check which interface your data object implements, and select the appropriate DataTemplate/HeirarchicalDataTemplate for this item.
The selector can both be applied to the container itself (ItemsControl.ItemTemplateSelector) and to your hierarchical data template (HeirarchicalDataTemplate.ItemTemplateSelector).
I think this is the lesser evil.
If you're not selecting from among multiple templates, you don't need to specify a data type on the template. If all of the objects in your tree implement your interface, just stick in a template using properties of that interface and you're good to go. You don't need to do anything in the template to make it specific to that interface.
If, for some reason, you need to do template selection based on what interface an object supports, you need to implement a template selector, and deal with the many-to-one problem that prevents WPF's built-in template selection mechanism from using interfaces in the first place. (That is, if you have a template for IFoo and one for IBar, what template do you use for an object that supports IFoo and IBar?)

WPF data binding and type conversion

I have a question regarding WPF binding and converting the data types seen by the UI objects in XAML.
I have a user control that I would like to reuse in different applications. The user control displays a thumbnail image and several TextBlocks to display person demographic information such as name and address. The user control is used in an MVVM design, so it’s bound to a ViewModel specific to the user control.
Following typical MVVM design principles, The ViewModel for the user control is often embedded in other ViewModels to make up a larger UI.
The user control view model expects a certain type (class) as its binding object.
However, the ViewModels in which the UC’s VM in embedded have entirely different object models, so they cannot simply pass-through their data to the UC’s VM. There needs to be a conversion of the parent VM’s data model to the UC VM’s data model.
My question is this: Is there a sanctioned way to perform this conversion?
I looked at IValueConverter and IMultiValueConverter and these do not look like the way to go.
I guess what I need is a sort of shim between the parent VM and the embedded UC VM where the parent VM’s data is converted to the format required by the UC VM.
Or, does it basically come down to I have to write a custom UC VM to handle whatever types the parent VM provides?
I agree with Ken, I think he has the answer. If you have n many configurations of your data that you want to pass into a common user control, then you want the owner of that configuration of data to convert it into a common form to be bound to the user control.
Each view that uses the control would have a corresponding view model that exposes a property in a common format:
public class SampleViewModel {
...
IUserControlData ControlData
{
get
{
// Do conversion here or do it early and cache it.
}
}
...
}
Then you would bind that property to your user control in the view
<common:CommonUserControl DataContext={Binding Path=ControlData} ... >
If the parent VM is a superset of the child VM, normally the parent VM would just hold a reference to the child VM. It would expose that reference as a property, and you would bind a ContentControl (or whatever) to that property.
Would this not solve your problem?
If you really want and need to do type conversions, the value converters are exactly what you want to use. That said, typically the type of conversions handled by things like IValueConverter are relatively simple and direct.
If, however, your top-level/parent/management user control needs to parse off bits and pieces of some larger type to the user controls which host its actual content, then that is the job of that top level control. Don't get all wrapped up in doing all of this in XAML. It's perfectly fine to parse off what you need and set these child control properties directly.
Probably not what you are looking for but this is a solution for DataGrid dynamic columns. With datagrid you can pass a parameter. http://www.codeproject.com/Articles/36496/Binding-a-Silverlight-DataGrid-to-dynamic-data-Part-2-editable-data-and-INotifyPropertyChanged.aspx

Resources