Changing DataTemplates at Runtime - wpf

I'd like to be able to swap out data templates at runtime, but without the
FindResource("fdds") as DataTemplate
Type of code I've seen a lot. I'd like to be able to just bind the template to look for the resource according to a property in my ViewModel. Conceptually I'd like to be able to do this, but the compiler obviously doesn't like it:
... ItemTemplate="{StaticResource {Binding Path=VMTemplate}}">
And then other commands would change the value of VMTemplate in the ViewModel. Is there a way to do something like this?

StaticResource extension is an immediate lookup when the XAML is parsed which means the Resource must be present at the start of the app. In order to set a template dynamically you will have to do something similar to the way your first line looks.
A possibility I have seen would be to make the DataTemplate have a custom control that extends ContentControl that has multiple DataTemplate properties that would then be able to select different templates based on a bound value from your View Model.

Related

How can I make a XAML style override a binding?

This question is for WinRT, but may also be applicable for Silverlight. Say I have databound the Background property of a ListView/ListBox, but I want a that databinding only to be in place when a particular theme is applied. I've implemented themes using Merged Dictionaries of XAML styles. When a different theme is applied, I want it to be statically defined by the style.
Is there a way to achieve this using XAML only?
I've tried placing the "Style" attribute after "Background" in the ListView tag itself, to see if the order of the properties mattered, but that did not seem to have any effect.
Nilzor -
This seems like the kind of place where you would use a Custom Converter. In this way, when the binding happens you can run logical tests and any arbitrary code to return the a value that is acceptable for binding.
WinRT project come with an example of the custom converter which i believe is named BooleanToVisibility Converter.
For the record: This does not NEED to be a conversion (i.e. bound object is bool, convert to Visibility and return it to the Visibility property) it can be a logical test -- The bound object is XYZ derives from ABC & if XYZ.Parent.SomeProperty == someValue return different ABC.
Here is a stack overflow link for Creating / Implementing them:
Binding to a property of a custom converter

How to set a parameter from a parent view into a view model which is declared as a static resource within a user control

I have the following (condensed) silverlight xaml for a view / viewmodel:
<UserControl x:Class=MyView>
<UserControl.Resources>
<MyViewModel x:Name="MyViewModel"/>
</UserControl.Resources>
<Grid DataContext="{Binding Source={StaticResource MyViewModel}}">
<UserControl>
Hopefully this looks familiar to you all.
However, I would like to create 2 instances of this same view user control, but to pass in a parameter to the view model to allow me to have slightly different view model data based on a property which I pass into the view model. Something like:
<UserControl x:Class=MyView>
<UserControl.Resources>
<MyViewModel x:Name="MyViewModel" Filter="Some value set at a higher level"/>
</UserControl.Resources>
<Grid DataContext="{Binding Source={StaticResource MyViewModel}}">
<UserControl>
The problem is that I can't hard code the Filter parameter inside the user control, but need to set it at a higher level. Is there a way to obtain the filter parameter from higher up via binding, and what would the syntax look like. I was hoping something like the following:
Either directly from the parent something like:
<MyView>
<MyView.ViewModel Filter="All">
</MyView>
<MyView>
<MyView.ViewModel Filter="Some">
</MyView>
Or from user control looking upwards, something like:
<UserControl.Resources>
<MyViewModel x:Name="MyViewModel" Filter="{Binding FilterTypeFromDataContextHigherUpTheTree}"/>
</UserControl.Resources>
but I don't know if is is possible to directly refer to the static resource view model from the parent in order to set a property, or what the syntax would look like.
I also don't know if there is an easier way to do this, as I suspect my approach is not very elegant.
The real question is how can I pass a parameter into a view model which is a static resourd
Though it's possible to store the ViewModel as a resource, we usually see the ViewModel set as the DataContext of a view. Then, if someone needs to access the ViewModel through the View, they just cast the DataContext to the proper ViewModel type and access it's properties directly.
If you want to go the Binding route for your Filter you have a couple of choices. You can set the Bnding Soure to RelativeSource.TemplatedParent if the child control is placed inside of the parent control in a template (or Style). You could also use ElementName, but only if the named element is inside of the same scope (in your example above, the named element would have to be somewhere inside of MyView).
The final option I can think of would be to expose a DependencyProperty for the filter on MyView and then set the binding of the ViewModel to that property. This would effectively bubble the filter so that it's accessible outside of MyView, but I don't like this approach at all because it's adding properties to the View just for the sake of passing them to the ViewModel. That should never happen. The ViewModel should always be accessible independantly of the View, which is why I recommend exposing it through the DataContext property (inferred) or through a custom property specifically for the ViewModel (explicit).
I sometimes do this with my ViewModels (e.g., instantiate them as a resource). When I do this, I have my VMs extend DependencyObject, for reasons I'll detail later.
I'd recommend that you move them to app.xaml and define them as resources of the application, where they will be available to everyone as a resource of the application. That way you can
<UserControl
DataContext="{StaticResource MyViewModel}" />
In addition, you can bind properties of your ViewModels together. That's why I extend DependencyObject.
Of course, this limits you to a single instance of MyViewModel, which may or may not work in your case. If it doesn't work, I'd define a ViewModel which contains the shared data, then bind to this via a static resource, as in your "looking upward" example.

Current binding value

I'm writing markup extension. I have XAML like this
<TextBlock Text="{ui:Test SomeInfo}" />
and TestExtension with constructor taking one string argument. I'm getting "SomeInfo" string so everything is find. Now I want to nest extensions and write something like
<TextBlock Text="{ui:Test {Binding PropName}}" />
and it does not work as is. I had to add constructor which takes one argument of System.Windows.Data.Binding type.
Now I need to know
How should I retrieve a current value from the Binding object?
When should I do this? Should I subscribe to changes some way or ask for that value every time in ProvideValue method?
Update1 PropName should be resolved against DataContext of TextBlock.
Update2 Just found related question: How do I resolve the value of a databinding?
Bindings like this will not work because your MarkupExtension has no DataContext and it does not appear in the visual tree and i do not think you are supposed to interact with binding objects directly. Do you really need this extension? Maybe you could make do with the binding alone and a converter?
If not you could create a dedicated class which has bindable properties (by inheriting from DependencyObject), this however would still not give you a DataContext or namescope needed for ElementName or a visual tree needed for RelativeSource, so the only way to make a binding work in that situation is by using a Source (e.g. set it to a StaticResource). This is hardly ideal.
Also note that if you do not directly set a binding the ProvideValue method will only be called once, this means that even if you have a binding in your extension it may not prove very useful (with some exceptions, e.g. when returning complex content, like e.g. an ItemsControl which uses the binding, but you set the extension on TextBlock.Text which is just a string), so i really doubt that you want to use a MarkupExtension like this if the value should change dynamically based on the binding. As noted earlier: Consider converters or MultiBindings for various values instead.

WPF binding to a non dependency property on a control template

I'm creating a WPF custom control as an auto learning exercise. My control has a ListView inside the template. I wanto my control user be able on defining the needed columns in his own Xaml, but I did not get the strategy on how to pass the columns to the inner listview since binding with FindAncestor complain that "Columns" is not a DependencyProperty.
Wekk the questions are:
How to achieve bind a property from xaml to the template when it is not a DP
Correct my design: I think there is something wrong: if someone would change completely my template, how should I let him use the Column collection ?
why not inherit from ListView directly? Then you have all the properties you need for the ListView and can also add you own properties to the class.
Then you can apply a custom Style to your control to make it look like you want. (Here you have a basic ListView Style that you can use and expand to your needs)
Sometimes binding to a property that is not a dependency property can be solved using the Binding Mode OneWayToSource
Have you tried that?

How do I databind a control in an item template to the item itself, and not one of its properties?

I've got a WPF ListBox that's databound to an ObservableCollection of type Employee. In the ItemTemplate, I'm binding the content of controls to various properties, as normal. But for one of the controls in the template, I've made a custom converter class that it uses, and I'd like the converter to get passed in the Employee object itself as the value, as opposed to one of its' properties. Is this easy to do? I don't want to resort to something like adding a read only property to Employee whose getter just says return this.
Thanks in advance!
Just use
{Binding}
or
{Binding Converter={...}}
i.e. without a Path.

Resources