Xamarin MultiBinding需要更高祖先级别或XAML树中命名项目的BindingContext

问题描述

我正在构建一个均质按钮的矩形网格,其中包含要在运行时设置的动态行和列。该规范在Xamarin中。所有最新版本等 整个项目可以在这里下载:https://github.com/BicycleMark/XamSweeper 我遇到的问题是XAML的MultiBinding部分。任何评论或建议都将非常出色

我使用嵌套StackPanels来创建网格,如下所示:

enter image description here

我成功创建了一个MultiValueConverter,用于调整大小正确显示的按钮。我已经用单元测试测试了转换器,并且它按预期运行。 [R,C]打印在每个按钮的测试中。这些是从正确绑定的模型中提取

我遇到的问题是将MultiBinding链接到我需要计算按钮大小的3个项目上:

每个按钮的宽度是使用这三个参数计算的

    按住按钮的框架的
  1. ActualWidth
  2. 模型按钮的数量
  3. 每个按钮之间的间距或填充
  4. 如果任何[1..3]为空返回50

每个按钮的高度是使用这三个参数计算的

    保持按钮的框架的
  1. ActualHeight
  2. 模型按钮的数量
  3. 每个按钮之间的间距或填充
  4. 如果任何[1..3]为空返回50

以下是描述的转换器:

    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,CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

及其通过的单元测试:

 [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));
    }

当前的问题是当我在Xamarin中绑定我的值时,我的转换器从XAML传递了Null 这是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>

转换器正在被调用,但是我每次都传递3个null。这是我要修复的绑定错误

整个项目可以在这里下载:https://github.com/BicycleMark/XamSweeper

解决方法

转换器正在被调用,但我每次都传递3个null。

您可以尝试将{ "Login":"Kapitan","Password":"M3030" } 设置为BindingContext,例如:

Frame

然后您就可以在<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 > 中获取值了。

但是Converter似乎不是现有的可绑定属性。