WPF: applying a converter to ItemsSource - c#

is it possible to apply a converter to a data source of a control in xaml?
or perhaps there is another way to do this.
Basically i have a custom control that accepts a specific type of object. that object is tightly bound to that control. I don't want to convert to this type all over my view model. So i would like to be able to bind to regular properties such as List and have it automatically translated to my object by a converter.
I've attempted something like this.
ItemsSource="{Binding CurrentTables, Converter={x:Static cconverters:SpyFilterDataObjectConverter}}"

Well, it doesn't seem good as for me to use such kind of converters. Basically, converter performs conversion operation only once, so you will not receive any updates. I've used different approach - just create some sort of wrapper that contains an initial collection (it should implement INotifyCollectionChanged) and some wrap strategies that converts your initial object to wrapped one.

x:Static has the syntax namespace:Type.StaticMember, you should instantiate the converter and expose it as a static property.
Alternatively you can create an instance in the Application.Resources in your App.xaml, then you can reference it as a static resource throughout the application using its key.

Related

Dynamically change XAML binding based on type

I have a list of objects that is being used as the source for a DataGrid. This list of objects is a base class type, of which there are 2 or more inherited types. I am trying to bind to properties of the base class to display as values in the columns of the DataGrid. The subclasses have different properties available to them which I would like to be able to display, so my question is, does XAML have a way to dynamically change the value of a binding based on the type that is being pointed to? I have thought about potentially doing this with a converter, but if I understand correctly, then I would have to write a different converter for each subclass property that I need to bind to. Any advice or suggestions are appreciated. Thanks
This is probably possible, with attributes and some reflection you could mark the properties that should go in the various columns and then auto-generate those. You could also create a sparse grid, with columns for all possible properties; this should also be possible via reflection and does not require any additional metadata.
(You can auto-create the columns based on the items using an attached property (like this) if the native DataGrid event is not sufficient for this.)
You can define multiple DataTemplates and specify the intended type through the DataType property. The correct template will be selected depending on the type of the bound object.
https://msdn.microsoft.com/en-us/library/system.windows.datatemplate.datatype(v=vs.110).aspx
The means to achieve this would be a CellTemplateSelector.
See this link.

Binding to a property by variable name (ideally from xaml)

I'm trying to databind (ideally from XAML as i know how to do this in code behind but it would be far from trivial to traverse my heavily templated tree just for that) to a property who's name i only know at runtime
What i would like to do is not the usual:
Content="{Binding TheProperty}"
But something like
Content="{Binding PropertyName=TheNameIsStoredInThisProperty}"
I'm trying to do this because i generate the UI from templates when binding to my plugins, but the UI is specified in a set of POCO and separate from the ViewModel, so i want to be able to generate my UI and still be able to wire it to the correct properties on the ViewModel, any advice is most welcome.
The immediate solution might be to bind to an arbitrary property in your VM with an IValueConverter that goes both ways, and the ConverterParameter is the string containing the source property name. Once inside the value converter you can use an interception pattern to Reflect out the value you need from the POCO. You can then pass the value up to the source property in the VM. Rather like a pipeline :) This will work but still leaves you with being notified when the POCO changes.
A Markup Extension seems plausible but likely to be brittle and provide naught in the way of performance improvement.
An Attached Behaviour still leaves you with having to Reflect and does not easily solve the problem of notifications originating in the POCO (AFAIK only Unity knows how to do that).

Implement binding extension on a property

I have a control that we could identify as similar to ListBox control. Each item is represented with one element (example TextBlock). What i would like is to change the layout of this item, so that it contains two TextBlocks. So I create a ControlTemplate, put a Border Grid, TwoTextBlocks, and all is well. Now the problem:
I need to be able to localize the text in the item, and I did this normally like this:
<... Text="{Binding Strings.SomeString, Source={StaticResource ApplicationResources}}" />
Now I need to be able to do the same with both TextBlocks. So i thought I need to create a custom type that this item will bind to, and expose two propertiws: Title and Description. If I expose this properties as string type, everything works ok, but I am loosing markup binding that I used previously. How to achieve the same with two properties? The result should be like:
<... Title="{Binding Strings.SomeString, Source={StaticResource ApplicationResources}}", Description="{Binding Strings.AnotherString, Source={StaticResource ApplicationResources}}" />
I was able to make Localization work with ResourcemManager class, but it gets even complicated in order to provide localization to be applied dynamically at runtime.
So, what do I need to do to be able to use above code? Then I just need to implement INotifyPropertyChanged on ApplicationResource and all is set.
Great!
I'm going to do the same thing you did here. Yeah, I have a solution but I'm not sure if it works till now.
First, we need a LocalizationManager which holds a dictionary.
For example, if you need to localize a user account window, just do this
<TextBlock Text="something, UsernameKey">
And the localizationManager will map UsernameKey to "Username" or other language
Second, a xaml extension which find the value of the key from LocalizationManager.
I wonder if this custom extension could derived from Binding extension, if so, this'll be very easy, just create a Binding Object to the target. If not, I think holding a WEAK reference to the UIElement by xaml extension to dynamic update the text is proper.
This solution is simple but not generic. There're some language read from right to left. It asks the application to show content from right to left.
So, I have another generic solution but more complex.
Instead of xaml extension, we use an attach dependency property.
Do it like this:
<TextBlock LocalizationManager.LocalizationKey="UsernameKey" />
So, the problem now is how to set "Text" property by LocalizationManager?
We use adapters, LocalizationManager will search proper adapter for type "TextBlock"
So, when the application is booting, we register some adapters to LocalizationManager:
LocalizationManager.Current.RegisterAdapter<TextBlock>(new TextBlockAdapter())
This solution is more generic, it supports any kind of control if you provide adapter, but as you see, this solution needs more work and much more complex than the former one.
I hope these design solutions could help you~

Why ever use a multi binding converter?

Couldn't I just use a single binding converter and as a parameter pass in the DataContext and from there pick what properties I want to use?
If you pass the whole object instead of the individual properties, then the binding expression will not be re-evaluated when the individual properties change. You will be losing the benefit of the INotifyPropertyChanged mechanism.
You might want to be more explicit and take in the minimum extra information (which is just generally good programming practice), or you may want information from more than one source - e.g. Your value might be dependent on a property of the datacontext and the checked state of a checkbox somewhere else in the view.
You can do that, but the binding will not update if the relevant properties change that way. Besides the updates Multibinding is needed for more complex bindings to different controls and data-objects.

ValueConverter with data binding

Is it possible to add a dependency property to a ValueConverter and bind it to a property of the object to which the converter is applied?
It isn't possible to do this in XAML. What you'd usually want to use for the sort of problem I'm guessing you have is a IMultiValueConverter.
If you really had to you could wire it up like you suggest in the code behind for your view but I really wouldn't recommend it. First it is much more difficult to manage and second your property won't be updated when the value you've bound to the new dependency property changes (i.e. the Convert method won't be called again). You're much better off using an IMultiValueConverter.

Categories