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.
Related
As far as I know, the default way to use a ObservableCollection that is bound to a listview is with model classes as elements (ObservableCollection<MyModel>). So when a listview element is selected, we use NavigateAsync and pass the model, which then can be used by the ViewModel to "fill itself".
The problem with this approach is, that it's not possible to use ViewModel properties for binding in the listview.
For example:
I have a View, ViewModel and Model "PickList", which contains a collection of "PickLine" objects - each having a View, ViewModel and Model themselves. The PickLine object contains a property "PickedQuantity" and a property "OpenQuantity". Now in my PickList view, I don't want to bind these two to separate items (e.g. two labels), but I want to have one label to display both I a format like for example "PickedQuantity / OpenQuantity". I know this example can be solved by using multi binding or something like this. But that's not the meaning of it all.
My PickLine ViewModel already has a property "QuantityString", that I want to bind to the label of a listview element via DataTemplate. But how can I do this. Is it even possible?
Make a property that combines the two other properties and bind to that. E.g.:
public string FullQuantity {get {return $"{PickedQuantity} / {OpenQuantity}";}}
Then in the setter for PickedQuantity and OpenQuantity, you will want to call whatever PropertyChanged method you have set up to notify the bindings of a property change and pass in the FullQuantity property name so elements that are bound to FullQuantity get updated when either PickedQuantity or OpenQuantity are changed.
This way, you are only binding one label's text to one property and that label would get updated when either of the two quantity properties are changed.
Note: I am unfamiliar with Prism, but this approach should work regardless of the Mvvm framework in use.
Your PickListViewModel should expose a collection property whose items are of type PickLineViewModel (not PickLine).
Whether you need an ObservableCollection<PickLineViewModel> depends on where changes can happen - in service / model that initially created the PickLines or in the GUI or both. In any way, you have to make sure the changes are propagated from one side (the collection of view models) to the other (the collection of models). Google wrapping observable collection as a starter (hint: avoid two-way sync if possible). These blog posts are old but still relevant and make a good reading. A trivial wrapping is described in this answer.
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).
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.
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.
I have two data-bound text boxes. One is bound to a string and the other to a number. The 'default' binding is set in XAML. Under some circumstances I need to reverse the bindings at runtime (the string is usually a prefix but sometimes it's a suffix).
I have the following code in my view model, called when the window is loaded:
Binding stringBinding = BindingOperations.GetBinding(view.seqLeft, TextBox.TextProperty);
Binding numberBinding = BindingOperations.GetBinding(view.seqRight, TextBox.TextProperty);
view.seqLeft.SetBinding(TextBlock.TextProperty, numberBinding);
view.seqRight.SetBinding(TextBlock.TextProperty, stringBinding);
After that the code loads the properties to which the binding refers.
The problem is that the 'new' binding doesn't seem to work. What have I missed? Is there a better way?
I might consider exposing Prefix and Suffix strings to which View can bind, then use logic within the ViewModel, or whatever backing object you're using, to fill those strings accordingly. This option neatly segments the business concern from the visual and simplifies what you have to keep track of in your view.
Why monkey around with the bindings at all? If you want to have a TextBox that's bound to one of two different things, create two TextBoxes, put them in the same location, and toggle their visibility based on whatever your swap condition is.
The only thing wrong with my code was the TextBlock.TextProperty in the SetBinding calls! They should, of course, have been TextBox.TextProperty but I'd messed with it so long I wasn't seeing the wood for the trees.