How is it possible to do multivalue binding in Silverlight?
I have to determine the Visibility of a Silverlight DataGrid column depending on the value present as part of Datacontext and other one from the QueryString.
I use MVVM Model of silverlight 5 and my plan is currently to define a property for querystring in code behind that can be binded to row visibility. But my problem clearly here is to pass multiple values for the IValueConverter implementation.
Can anyone provide a simple example to solve my problem?
Multi binding is not supported out of the box in Silverlight.
But with the introduction of customer markup extensions in Silverlight 5, this can be achieved.
There's a good example on code project: http://www.codeproject.com/Articles/286171/MultiBinding-in-Silverlight-5.
Alternatively, in this particular example you can have public boolean a property in your view model which uses the QueryString Value along with the other value you are concerned in DataContext and decides whether the column needs to be visible or not. You can then databind this property to your column's IsVisible property. (Along with a value converter which returns Visbility.Visble /Visibility.Collapsed depending on the value of the boolean property value)
Related
Before I start to explain my problem: The Slider is just an example for the following problem. I work on a custom control, that has to do a very similar thing like the slider does here:
Scenario:
I have bound a Slider.Value to my ViewModel property called MyValue.
I have defined the Maximum of the Slider to be 100.
Now I set the Property MyValue to 200.
What is the problem?
The Slider will internally coerce the value to be 100.
But the property MyProperty isn't being updated.
In my case (the custom control I built), I need to continue with the coersed value (100) later on, NOT the old (200) value.
Question:
Is there anything I can do in my custom control?
For example I tried myControl.GetExpression(MyValueProperty).UpdateSource(); in both my CoerseValueCallback and PropertyChangedCallback, but no matter what I try, the setter of the bound ViewModel-property is NEVER called and the property stays out of sync.
Bind the Maximum property of your Slider to another view model property and implement logic to ensure that your values are always within the valid range in your view model class.
The control rightfully coerces the values but the logic of synchronizing them should be implemented in the view model class.
Your custom control should be able to simply set the source property of its current DataContext whenever the value is coerced though.
this.GetBindingExpression(Slider.ValueProperty).ResolvedSourcePropertyName should give you the name of the source property and then you can for example set it using reflection if calling UpdateSource() on the BindingExpression doesn't work.
Suppose I have a object ListCollectionView and bind it to a datagrid. I bind the object's Name property to a TextBox(one of the datagrid's column)'s Text property and add my specific ValidationRule.
Now I want to the rule to check if the Name property is duplicated, I need to check other objects in the ListCollectionView, if there are objects' Name property equals to this Name, the validate result will be false.
My question is this check can apply only to the edited object, So only this object will become red when its Name is duplicated, but how can I also make check to other list objects, make the other objects which Name property equals to this edited one also become red? Thanks.
You are correct that the ValidationRule only has access to the data it is bound to. However you can write a custom ValidationRule - I've got a blog post detailing it here, and you can then add extra properties to it so you can inject the appropriate data that your bound value should be checked against.
However you will strike one tricky problem - the cells in the datagrid have no natural access to the DataContext of the datagrid because datagrid columns are not in the visual tree. To get around that problem you can use a static proxy object which contains (binds to) the ListCollectionView, this proxy object can then be bound to by the ValidationRule (example 1, example 2).
I have a read-only datagrid bound to a domain data source. The data that I'm binding to has an ID property that I'm resolving on the grid through a converter (a simple int -> string mapping). The domain data source also has a GroupDescriptor on it, and this works, except I'm grouping by that column which has a converter on it.
Unfortunately the group header doesn't use the Converter and therefore just displays the ID, which is not desirable. I can replace the control template for the group header and explicitly use a converter on the template, but this is obviously not an ideal solution as I'm hard-coding the template to the converter.
Is there a way to use a converter on a group descriptor?
i found out that if you create a PropertyGroupDescription in code, it allows you to supply an IValueConverter in the constructor, so this would appear to be an answer.
I have a ListBox bound to an ObservableCollection of type T - each ListBoxItem is a checkbox with IsChecked bound to a bool property in T. I want to validate the checked items in the ListBox so that at least one checkbox must be ticked - if none of the check boxes are ticked I want to show a red border (standard validation notification) around the ListBox.
How do I go about doing that? Can I use ValidatesOnDataErrors?
Implement IDataErrorInfo in the class that exposes the ObservableCollection<T> property and make the indexer return an error for that property's name if all of the objects in the collection have a value of false in their boolean property. Then use the DataErrorValidationRule in your binding's ValidationRules.
Your goal is to validate selected items of a ListBox: at least one selected item is required. First, there are different ways to handle the selection itself:
a) You can use the ListBox selection mechanism via ListBox.SelectedItem.
I guess, you can specifiy the binding as SelectedItem="{Binding SelectedThing, ValidatesOnNotifyDataErrors=True}" and WPF's regular validation works. Not sure, if this works well with multi-selection.
b) You can use ListBox.SelectedItems. Binding is not possible and needs to be faked via code behind event handler. Thus, WPF's validation cannot trigger here.
c) You use your own IsSelected property (or similar) per item, either explicitely bound to your viewmodel via CheckBox or implicitely via ListBoxItem.IsSelected (via ListBox.ItemContainerStyle).
From here you could create a bool IsValidSelection property in your viewmodel that updates whenever the selection changed. Or you can run validation rules on any of the resulting properties of your viewmodel (e.g. SelectedItems). However, you don't validate the bound ListBox.ItemSource itself! Therefore WPF's standard mechanisms don't work (the list box doesn't get a red border or whatever).
Workarounds
You can explicitely create error notifications by showing an otherwise invisible Label and binding its visibility to the above-mentioned bool IsValidSelection property. This is a very explicit way, not using WPF validation at all.
You can modify your INotifyDataErrorInfo (or similar) implementation to trigger errors on a different property name. This is not possible, if you use a generic ValidatableViewModel<T> (like me). I guess this was the intention of the other answer.
I am using WPF and the MVVM pattern in my user interface. In my ViewModel I have a List containing distances in millimetres, which I display in a ListView by binding ListView.ItemsSource to the List. However, I would like the values displayed to use a more natural unit - either metres or feet depending on the state of a "metric" checkbox.
I have written a couple of simple classes, MillimetresToMetresConverter and MillimetresToFeetConverter, both of which implement IValueConverter. Although I can set the Converter property on my data binding to one or the other, I am unsure how to change between these converters when the state of the checkbox changes.
My plan was to have a field "IValueConverter lengthConverter" on my ViewModel which I could set to one converter or the other, then in my XAML do ...="{Binding Converter={Binding Path=lengthConverter}}" - unfortunately this does not work since Converter is not a dependency property.
How can change the converter used by the data binding at runtime?
Most of the time when using the MVVM methodology, you can do the formatting task in the VM classes. In your case, you could add a Format property to the VM class, and based on the value of the Format property, return a well formated string.
See this discussion for more information.
If I may suggest a simple alternative solution: Create a small FormatMillimetresConverter in your ViewModel, whose UseMetric property is bound to the "metric" checkbox.