Reputation: 667
I need to make a calculation in my view model to show a percentage range between two columns in a grid.
I'm trying to set a string property to set the values in the view model as below,
// These two below values/ratio would be calculated dynamically,
public string firstColValue = "3*";
public string secondColValue = "7*";
<Frame CornerRadius="8" Grid.Row="0" HorizontalOptions="FillAndExpand" HeightRequest="8">
<Grid HorizontalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding firstColValue}">
</ColumnDefinition>
<ColumnDefinition Width="{Binding secondColValue}">
</ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="8">
</RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" HeightRequest="8" HorizontalOptions="FillAndExpand" BackgroundColor="Lime"></Label>
<Label Grid.Row="0" Grid.Column="1" HeightRequest="8" HorizontalOptions="FillAndExpand" BackgroundColor="Blue"></Label>
</Grid>
</Frame>
This is throwing me a run time exception. I'm trying to set the width of the two columns dynamically from the view model property.
Please let me know how to achieve this.
Upvotes: 0
Views: 2252
Reputation: 9356
This error is because you are Binding a string to the Width which require another object.
To fix this one of the solution would be using a Converter
that will convert your type (the one coming from the ViewModel) into the type expected for the Grid Width. More info about Converters here
The Converter you need would look like this:
public class IntToGridLengthConverter : IValueConverter
{
public IntToGridLengthConverter()
{
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var intValue = System.Convert.ToInt32(value);
return new GridLength(intValue, GridUnitType.Star);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then in the XAML you just need to use it.
Adding a new section to the XAML and calling the Converter
<ContentPage.Resources>
<ResourceDictionary>
<local:IntToGridLengthConverter x:Key="gridLengthConverter" />
</ResourceDictionary>
</ContentPage.Resources>
Then using the Converter in your Bindings
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding firstColValue, Converter={StaticResource gridLengthConverter}}" />
<ColumnDefinition Width="{Binding secondColValue, Converter={StaticResource gridLengthConverter}}"/>
</Grid.ColumnDefinitions>
As you can see I am using the Key that was set in the previous part.
One small change you need to do in your ViewModel properties is that now they should be of type int
(integer). So in your ViewModel you would set only the integer part of the value you wanna set, for example:
firstColValue = 7;
secondColValue = 3;
The work to convert these values into 7*
and 3*
respectively will be responsible of the Converter.
Using Converters will prevent you from using Xamarin.Forms elements in your ViewModels as these should be agnostic. Also, this Converter can be reused in any other page you need.
Hope this helps.-
Upvotes: 3
Reputation: 7199
Your problem is the object you are trying to bind. You need to use a GridLength
For example
GridLength test = new GridLength(3, GridUnitType.Star); // which is "3*"
Just update your ViewModel to return a value of type GridLength
Upvotes: 2