WPF and MVVM: Changing data binding converter at runtime - wpf

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.

Related

WPF MVVM - Binding DataGrid to ObservableCollection of Model

I am pretty new to WPF MVVM, so pardon me if I understood MVVM concepts wrongly.
I have a DataGrid in my View, which I have bound the ItemsSource to an ObservableCollection<M> in the ViewModel. The M class is a Model class. However, the M class has bool properties, which are to be displayed in the DataGrid as "Yes/No" strings.
Currently, I am using a Converter to convert the bool value to string. But, it just feels wrong for the ViewModel to expose a list (ObservableCollection) of a Model to the View. I have also read that in MVVM, conversions should be done at ViewModel. So, what is the right way to implement this the MVVM way for a DataGrid?
In an ideal world, you would wrap your Model objects in their own ViewModel so that your ObservableCollection contains a ViewModel type with those bool Model properties converted to Yes/No string properties.
However, in a pragmatic world, if you are not editing those values, I wouldn't bother except to note that if you are exposing many of those bool properties and have many thousands of rows, you will take a performance hit on rendering the grid while the DataGrid instantiates a Converter per property and row.
Using converters is not a wrong way. As per my suggestion, you should bind the data as you're doing now and in the view you can create and use a BoolToStringConverter for converting the boolean value to yes or no.

Passing QueryString Value For Silverlight Grid Row

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)

How to create a dependency property in Silverlight using MVVM?

let say there is a textbox and i want to control the visibility of this control using MVVM, is there a sample on how to do this? First create a dependency property then get it hooked up in the ViewModel. Thanks.
Typically, you wouldn't need to use a dependency property in this case. Dependency properties really only need to be implemented for things like controls themselves, not for determining behavior. Behavior, such as the visibility of an element, can be handled directly via data binding.
Your ViewModel would just have some property, and you'd bind the TextBox.Visibility property directly to the ViewModel property.
The one "sticky point" is that you often will want to have some type of IValueConverter that will convert from your property type to a Visibility enum.

Silverlight - Sample Data - Complex objects

I really like using the sample data binding at design time for Silverlight.
It is easy to use it when you need to return string values.
In my case, I am trying to bind to my ViewModel one of whose properties returns a SolidColorBrush. How do I setup the sample data to return a SolidColorBrush value?
Here is what the string based properties look in the sampleData.xml file.
<ViewModels:MyViewModel AlphaValue="Abcd" ColorValue="????"/>
How should I format ColorValue to return a SolidColorBrush?
What I am trying to do:
I have a textblock with its foreground set to Foreground="{Binding ColorValue}". The TextBlock is invisible on the design surface as its not getting a value from the sampledata.xml file. Where as another textblock on which I have only text property set to a binding value, appears correctly on the design surface.
You need to look at creating a value converter. Look at this and it should give you an understanding of what you need to do. http://msdn.microsoft.com/en-us/library/system.windows.data.binding.converter.aspx

Dynamically specify and change a Silverlight DataGrid's columns during runtime (MVVM)

What's the best method of dynamically specifying DataGrid columns in the Silverlight DataGrid control at runtime following the MVVM pattern?
What I'd like to do would be bind the "DataGrid.Columns" property to a property in my ViewModel so that, if the user adds/removes columns, I simply update the ViewModel property and the DataGrid would change. Problem is, the "DataGrid.Columns" property can't be bound to (I don't think).
Because this property isn't available nor is the DataGrid control itself available at the ViewModel level, my current approach is to step outside of the MVVM pattern for this particular implementation and capture certain events in View's code-behind using MVVM Light's Messenger class and then talk directly with the DataGrid control to achieve this capability. I know this is a general statement to this approach without details but is there an easier way... or maybe not so much easier, but a better way that adheres to the MVVM pattern a little better?
It's driving me crazy that the DataGrid control's Columns property can't be bound... seems like such a simple thing.
FYI - Before it's suggested to use AutoGenerateColumns = True, the class being bound for each item in the collection that's bound to DataGrid.ItemsSource does not have individual properties to identify what is bound to the columns... it's a collection property that contains the columns in order to keep them completely dynamic so that particular path is out. Also, handling the AutoGeneratingColumns and using e.Cancel to show/hide columns is also iffy for this same reason (I think).
I agree that it is a pain that DataGrid.Columns cannot be bound to. My recommendation here would be to define your columns in the ViewModel in an ObservableCollection. In the View (code behind), handle the CollectionChanged event of this ObservableCollection, and modify the DataGrid.Columns in code.
While this solution is less elegant, it is straightforward. For your ViewModel, you can unit test that the CollectionChanged event is raised properly when columns are added, removed or moved. The View code cannot be tested, so I guess this is something you need to live with. The advantage is that, if some day the DataGrid.Columns property can be databound, it will be easy to refactor this to remove the code behind.
Another way (I think) would be to create an attached behavior or a Blend behavior to take care of this. Attach it to the DataGrid; instead of binding to the DataGrid.Columns directly, bind to a property on the behavior, and have the behavior modify the DataGrid (the AssociatedObect) directly.
Does that make sense?
Cheers,
Laurent

Resources