使用 MVVM 在 Xamarin.Forms 中绑定 属性

Binding property in Xamarin.Forms using MVVM

我在使用 Xamarin.Forms 和 MVVM 制作游戏时遇到问题。

游戏中有一艘由用户控制的潜艇,有地雷落下,用户必须避开这些地雷。地雷是在运行时使用 2 个计时器生成的,因此我在 XAML.

中用 CollectionView 表示它们

我已经使用 WPF(也使用 WinForms)制作了这个游戏,在那种情况下,我使用 Canvas 作为游戏区域(ItemsControl 用于地雷)并且绑定效果很好。 现在(使用 Xamarin.Forms)我尝试使用 AbsoluteLayout 和 RelativeLayout 实现游戏区域,但总是收到例如。以下输出 (RelativeLayout):

[0:] Binding: '160' cannot be converted to type 'Xamarin.Forms.Constraint'

当前XAML编码:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SubmarineGame.View.GamePage"
             Title="Submarine Game">
    <ContentPage.Content>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>

            <RelativeLayout Grid.Row="0">
                <Image Source="sea.png" 
                       RelativeLayout.WidthConstraint="{ConstraintExpression 
                    Type=RelativeToParent, 
                    Property=Width, 
                    Factor=1}" 
                       RelativeLayout.HeightConstraint="{ConstraintExpression 
                    Type=RelativeToParent, 
                    Property=Height, 
                    Factor=1}" 
                       Aspect="AspectFill" />
                <ImageButton Command="{Binding ExitCommand}" 
                             CornerRadius="50" 
                             RelativeLayout.WidthConstraint="{ConstraintExpression Constant=50}" 
                             RelativeLayout.HeightConstraint="{ConstraintExpression Constant=50}" 
                             RelativeLayout.XConstraint="{ConstraintExpression 
                    Type=RelativeToParent, 
                    Property=Width, 
                    Factor=0.9}" 
                             RelativeLayout.YConstraint="{ConstraintExpression 
                    Type=RelativeToParent, 
                    Property=Height, 
                    Factor=0.1}" 
                             Source="pausebutton.png" />
                <CollectionView ItemsSource="{Binding Mines}" 
                                BackgroundColor="Transparent" 
                                RelativeLayout.WidthConstraint="{ConstraintExpression 
                    Type=RelativeToParent, 
                    Property=Width, 
                    Factor=1}" 
                                RelativeLayout.HeightConstraint="{ConstraintExpression 
                    Type=RelativeToParent, 
                    Property=Height, 
                    Factor=1}" 
                                FlowDirection="MatchParent">
                    <CollectionView.ItemTemplate>
                        <DataTemplate>
                            <Image RelativeLayout.WidthConstraint="{ConstraintExpression Constant=64}" 
                                   RelativeLayout.HeightConstraint="{ConstraintExpression Constant=64}" 
                                   RelativeLayout.XConstraint="{Binding X}" 
                                   RelativeLayout.YConstraint="{Binding Y}" 
                                   Source="nuclearbomb.png" />
                        </DataTemplate>
                    </CollectionView.ItemTemplate>
                </CollectionView>
                <Image RelativeLayout.WidthConstraint="{ConstraintExpression Constant=64}" 
                       RelativeLayout.HeightConstraint="{ConstraintExpression Constant=64}" 
                       RelativeLayout.XConstraint="{Binding Submarine.X}" 
                       RelativeLayout.YConstraint="{Binding Submarine.Y}" 
                       Source="submarine.png" />
            </RelativeLayout>

            <StackLayout Orientation="Horizontal" HorizontalOptions="Start" Grid.Row="1">
                <Label Text="Game time: " />
                <Label Text="{Binding GameTime}" />
            </StackLayout>
            <StackLayout Orientation="Horizontal" HorizontalOptions="End" Grid.Row="1">
                <Label Text="Destroyed mines: " />
                <Label Text="{Binding DestroyedMineCount}" />
            </StackLayout>
        </Grid>
    </ContentPage.Content>
</ContentPage>

ViewModel 中的潜艇和水雷:

public ObservableCollection<Shape> Mines { get; set; }
public Submarine Submarine               { get; set; }

形状 class:

public class Shape : ViewModelBase
{
    private Int32 _x;
    private Int32 _y;

    public Int32 X 
    { 
        get { return _x; }
        set
        {
            if (_x != value)
            {
                _x = value;
                OnPropertyChanged();
            }
        }
    }
    public Int32 Y
    {
        get { return _y; }
        set
        {
            if (_y != value)
            {
                _y = value;
                OnPropertyChanged();
            }
        }
    }
    public Int32 Width  { get; set; }
    public Int32 Height { get; set; }
    public Int32 Weight { get; set; }

}

潜艇class:

public class Submarine : Shape
{
    public DelegateCommand StepCommand { get; set; }
}

所以问题是如何解决转换问题?我是否为游戏区域(甚至地雷)使用了错误的布局? Xamarin 开发人员在这种情况下使用什么方法或模式来实现 MVVM 架构?

感谢您的宝贵时间,抱歉我的英语不好!

来自错误: [0:] Binding: '160' cannot be converted to type 'Xamarin.Forms.Constraint' 您可以看到它无法将整数转换为绑定表达式所期望的类型 Constraint

当你这样做时:

                            <Image RelativeLayout.WidthConstraint="{ConstraintExpression Constant=64}" 
                                   RelativeLayout.HeightConstraint="{ConstraintExpression Constant=64}" 
                                   RelativeLayout.XConstraint="{Binding X}" 
                                   RelativeLayout.YConstraint="{Binding Y}" 
                                   Source="nuclearbomb.png" />

当预期类型为 Constraint 时,您将绑定到整数 X 和 Y。

就我个人而言,我会避免对布局使用约束,而更喜欢 Grid,但如果您愿意,可以通过更改约束绑定的类型来解决此错误(XY, 等) 到 Constraint 并使用辅助方法转换数值 Constraint.Constant(myConstraintAsADouble).