Xamarin MultiBinding 需要更高祖先级别的 BindingContext 或 XAML 树中的命名项
Xamarin MultiBinding Needs BindingContext from higher ancestor level or named Items in XAML tree
我正在构建一个由同类按钮组成的矩形网格,其中包含要在运行时设置的动态行和列。代码在 Xamarin 中。所有最新版本等。
整个项目可以在这里下载:https://github.com/BicycleMark/XamSweeper
我遇到的问题是 XAML 的多绑定部分。任何评论或建议都会非常好
我使用 Nested StackPanels 创建了这样的网格:
我成功地创建了一个 MultiValueConverter 用于调整大小 正确显示的按钮。我已经用单元测试测试了转换器,它按预期运行。 [R,C] 打印在每个按钮的测试中。这些是从正确绑定的模型中提取的
我遇到的问题是将 MultiBinding 链接到 3 个项目,我需要计算按钮的大小:
每个Button的宽度是用这三个参数计算出来的
- 按住按钮的框架的实际宽度
- 模型按钮的 列数
- 每个按钮之间的间距或填充
- 如果任何 [1..3] 为空 return 50 <--- 这就是我 return 因为我的绑定不起作用
每个Button的高度是用这三个参数计算出来的
- 按住按钮的框架的实际高度
- 模型按钮的行数
- 每个按钮之间的间距或填充
- 如果任何 [1..3] 为空 return 50 <--- 这就是我 return 因为我的绑定不起作用
这是描述的转换器:
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();
}
}
及其通过的单元测试:
[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 个空值。这是我要修复的绑定错误
整个项目可以在这里下载:https://github.com/BicycleMark/XamSweeper
The Converter is Getting Called but I am passing 3 nulls each time.
您可以尝试将 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
.
中获取值
但是 ActualWidth
似乎不是现有的可绑定 属性。
我正在构建一个由同类按钮组成的矩形网格,其中包含要在运行时设置的动态行和列。代码在 Xamarin 中。所有最新版本等。 整个项目可以在这里下载:https://github.com/BicycleMark/XamSweeper 我遇到的问题是 XAML 的多绑定部分。任何评论或建议都会非常好
我使用 Nested StackPanels 创建了这样的网格:
我成功地创建了一个 MultiValueConverter 用于调整大小 正确显示的按钮。我已经用单元测试测试了转换器,它按预期运行。 [R,C] 打印在每个按钮的测试中。这些是从正确绑定的模型中提取的
我遇到的问题是将 MultiBinding 链接到 3 个项目,我需要计算按钮的大小:
每个Button的宽度是用这三个参数计算出来的
- 按住按钮的框架的实际宽度
- 模型按钮的 列数
- 每个按钮之间的间距或填充
- 如果任何 [1..3] 为空 return 50 <--- 这就是我 return 因为我的绑定不起作用
每个Button的高度是用这三个参数计算出来的
- 按住按钮的框架的实际高度
- 模型按钮的行数
- 每个按钮之间的间距或填充
- 如果任何 [1..3] 为空 return 50 <--- 这就是我 return 因为我的绑定不起作用
这是描述的转换器:
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();
}
}
及其通过的单元测试:
[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 个空值。这是我要修复的绑定错误
整个项目可以在这里下载:https://github.com/BicycleMark/XamSweeper
The Converter is Getting Called but I am passing 3 nulls each time.
您可以尝试将 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
.
但是 ActualWidth
似乎不是现有的可绑定 属性。