Reputation: 555
I am Building a rectangular Grid of Homogeneous Buttons with Dynamic Rows and Columns to Be set at Runtime. The Code is in Xamarin. All the latest versions etc. Entire Project can be Downloaded here: https://github.com/BicycleMark/XamSweeper The Problem I am having is the MultiBinding Portion of the XAML. Any review or suggestions would be super-excellent
I used Nested StackPanels to create the Grid like this:
I succeeded at creating a MultiValueConverter for sizing the Buttons which are appearing correctly. I have Tested the Converter with a Unit Test and it functions as Expected. the [R,C] is printed in the Test of each Button. These are pulled from Model which is bound Correctly
The problem I am having is in Linking the MultiBinding to 3 Items I need to calculate Size for the Buttons:
The Width of Each Button is calculated with these three parameters
The Height of Each Button is calculated with these three parameters
Here is the Converter Described:
public class SizeConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null || values.Length <3 || values[2] == null || values[1] == null || values[0] == null)
return 50;
int numItems = (int)values[2];
int separatorSize = (int)values[1];
double frameSize = System.Convert.ToDouble(values[0]) ;
int totalSeparatorSize = (numItems - 1) * separatorSize;
int remainingArea = System.Convert.ToInt32(frameSize) - totalSeparatorSize;
return remainingArea / numItems;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
And Its Unit Test Which Passes:
[DataRow(100, 2, 4)]
[DataTestMethod]
public void Test_Piece_Sizing(double frameSize, int separatorSize, int numItems)
{
var sizeConverter = new SizeConverter();
object[] values = new object[] { frameSize, separatorSize, numItems };
Assert.AreNotEqual(0,sizeConverter.Convert(values, typeof(int), null, System.Globalization.CultureInfo.CurrentCulture));
}
The issue at hand is when I bind My Values in Xamarin My Converter gets Null passed from my XAML Here is the XAML
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="http://prismlibrary.com"
prism:ViewModelLocator.AutowireViewModel="True"
xmlns:local="clr-namespace:Sweeper.Controls;assembly=Sweeper"
xmlns:cvt="clr-namespace:Sweeper.Views.Converters;assembly=Sweeper"
x:Class="Sweeper.Views.GamePage"
Title="Game"
x:Name="page">
<ContentPage.Resources>
<cvt:SizeConverter x:Key="SizeConverter" />
<cvt:CoordinateConverter x:Key="CoordinateConverter" />
</ContentPage.Resources>
<Frame BackgroundColor="DarkSeaGreen" CornerRadius="15" Padding="15">
<Grid RowDefinitions="*,3*">
<Frame Grid.Row="0" Padding="0">
<Grid ColumnDefinitions="*,*,*" Padding="0" >
<Frame Grid.Column="0">
<Label HorizontalOptions="Center" VerticalOptions="Center">
<Label.Text>
<MultiBinding Converter="{StaticResource CoordinateConverter}">
<Binding Path="Board.Rows" />
<Binding Path="Board.Columns" />
</MultiBinding>
</Label.Text>
</Label>
</Frame>
<Frame Grid.Column="1">
<Button Text="Ok"></Button>
</Frame>
<Frame Grid.Column="2">
<Label HorizontalOptions="Center" VerticalOptions="Center" Text="{Binding Game.Time}"/>
</Frame>
</Grid>
</Frame>
<Frame Grid.Row="1" x:Name="frameButtons" Padding="4" HasShadow="True" >
<StackLayout HorizontalOptions="FillAndExpand" Orientation="Vertical" Spacing="4"
BindableLayout.ItemsSource="{Binding Board.RowItems}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout BindableLayout.ItemsSource="{Binding}" Orientation="Horizontal" HorizontalOptions="Center">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Frame Padding="0" HasShadow="False" BackgroundColor="LightBlue" >
<Button Text="{Binding Name}" FontSize="Body" HorizontalOptions="Center" TextColor="Navy"/>
<Frame.WidthRequest>
<MultiBinding Converter="{StaticResource SizeConverter}" >
<MultiBinding.Bindings>
<Binding Source="x:Reference frameButtons" Path="ActualWidth" />
<Binding Source="x:Reference frameButtons" Path="Padding" />
<Binding Source="x:Reference frameButtons" Path="BindingContext.Board.Columns" />
</MultiBinding.Bindings>
</MultiBinding>
</Frame.WidthRequest>
<Frame.HeightRequest>
<MultiBinding Converter="{StaticResource SizeConverter}" >
<MultiBinding.Bindings>
<Binding Source="x:Reference frameButtons" Path="ActualHeight"/>
<Binding Source="x:Reference frameButtons" Path="Padding" />
<Binding Source="x:Reference frameButtons" Path="BindingContext.Board.Rows" />
</MultiBinding.Bindings>
</MultiBinding>
</Frame.HeightRequest>
</Frame >
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</Frame>
</Grid>
</Frame>
</ContentPage>
The Converter is Getting Called but I am passing 3 nulls each time. This is the Binding Error I am trying to repair
Entire Project can be Downloaded here: https://github.com/BicycleMark/XamSweeper
Upvotes: 0
Views: 1408
Reputation: 14956
The Converter is Getting Called but I am passing 3 nulls each time.
You could try to set the BindingContext
to the Frame
like:
<Frame Padding="0" HasShadow="False" BackgroundColor="LightBlue" BindingContext="{x:Reference frameButtons}">
<Button Text="{Binding Name}" FontSize="Body" HorizontalOptions="Center" TextColor="Navy" Clicked="Button_Clicked"/>
<Frame.WidthRequest>
<MultiBinding Converter="{StaticResource SizeConverter}" >
<MultiBinding.Bindings>
<Binding Path="ActualWidth" />
<Binding Path="Padding" />
<Binding Path="BindingContext.Board.Columns" />
</MultiBinding.Bindings>
</MultiBinding>
</Frame.WidthRequest>
<Frame.HeightRequest>
<MultiBinding Converter="{StaticResource SizeConverter}" >
<MultiBinding.Bindings>
<Binding Path="ActualHeight" />
<Binding Path="Padding" />
<Binding Path="BindingContext.Board.Rows" />
</MultiBinding.Bindings>
</MultiBinding>
</Frame.HeightRequest>
</Frame >
then you could get the value in your Converter
.
But ActualWidth
seems not be an existing bindable property.
Upvotes: 1