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?)
Related
I am trying to create editable tree widget. There are many samples how to make editable columns for Table, for example by using cellrenderer and propertyCellRendererFactoryFunc - which is quite awesome. Unfortunately I can't find any useful example for VirtualTree/Tree. Is it even possible to create one without deep Tree source code editing?
Here is one approach for VirtualTree:
VirtualTree uses normal widgets for the tree items, so the idea is to taylor the way these items are created, in order to modify their appearance.
This is achieved through a delegate. Use tree.setDelegate() to set a custom delegate on a tree.
The delegate itself can be a native JS object (map). It has to conform to the IVirtualTreeDelegate interface, meaning the delegate object exposes some methods from a predefined set (like 'bindItem', 'createItem', ...). See the code of this demo for a general example.
In your case, you want to provide a createItem method in your delegate, along with any other supporting methods (e.g. bindItem). There is a somewhat more complicated example that does that, which uses an instance of itself as the delegate.
HTH
I have a custom usercontrol created by myself which belongs to mine baseControls elements. It's a special button which have some animations and other cool features. It will be used stand alone in some applications, and wrapped into containers in other applications. In the last case I will have an userControl "WRAPPER" that will contain my "BUTTON". I need to reveal some properties (dependency properties) of the BUTTON at the WRAPPER level (i.e. ButtonStatus, Text, etc). A sort of tunneling of properties. I googled a little bit and I found an interesting solution at this link: Exposing Bindings as Properties of a Control but I don't know if its be best solution or if it's the only one! It consist in a sort of duplication of the properties at WRAPPER level...
Any Hints about this issue !??!
Thanks in advance
Paolo
Here is another StackOverflow thread that shows a solution on how to expose the inner element dependency properties. Basically, you add the the dependency property to the WRAPPER and bind the BUTTON property to the wrapper property. If the value flow is always from WRAPPER to BUTTON, you can use TemplateBinding instead of Binding.
One solution is, as you suggest, adding properties to the wrapper that mirror (and are bound to) the underlying properties you want to expose.
The other solution is to look into using attached properties.
I'm writing a WPF application while mostly adhering to the MVVM design pattern. The application has various educational modules broken up into different categories to be accomplished by the user. The modules are organized into a hierarchical menu. My ViewModel has a class called MenuPageViewModel which exposes the information needed to render a MenuNode. Naturally, the terminal elements in the menu tree have content that I'd like to display to the user. This content can be one of many different types of modules. Currently, when the user selects a module in the menu, I can't see any way around using a large conditional block to determine what type of ViewModel I'd like to return to be displayed based on the type of the MenuItem's Content Property. For example...
if (CurrentlySelectedMenuItem.Content is Lesson)
return new LessonViewModel(CurrentlySelectedMenuItem.Content as Lesson);
if (CurrentlySelectedMenuItem.Content is SkillsCheck)
return new SkillsCheckViewModel(CurrentlySelectedMenuItem.Content as SkillsCheck);
Can someone give me a hint to a more elegant and maintainable approach? Right now, if I add a new module type, I have to remember to update this conditional block, and that just sort of annoys me.
Thanks.
If you are using Unity/Prism then using the container to resolve the object would be my first preference.
_container.Resolve(Type.GetType(strObjectType)) as BaseViewModel;
where strObjectType is a string with the type of class you want to create (eg "LessionViewModel" )
if you are not using Unity, then reflection works
Activator.CreateInstance(strObjectType) as BaseViewModel;
with both solutions you need to have the string with the class type on your menuItem.
A third option is to have a factory, but it would probably end up having a conditional situation within it or will contain the code i just listed.
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.
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.