【问题标题】:Binding property in Xamarin.Forms using MVVM使用 MVVM 在 Xamarin.Forms 中绑定属性
【发布时间】:2022-01-28 05:49:21
【问题描述】:

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

游戏中有一艘由用户控制的潜艇,并且有地雷掉落,因此用户必须避开这些地雷。地雷是在运行时使用 2 个计时器生成的,所以我用 XAML 中的 CollectionView 来表示它们。

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

[0:] 绑定:“160”无法转换为类型 '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; }

Shape 类:

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

}

潜艇类:

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

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

感谢您的宝贵时间,对不起我的英语!

【问题讨论】:

    标签: c# xaml xamarin.forms mvvm


    【解决方案1】:

    从错误中: [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).

    【讨论】:

    • 好答案。更改X 等类型的替代方法是添加具有正确类型的新只读属性:Constraint XC =&gt; Constraint.Constant(X);。然后在 xaml 中,绑定到 XC 而不是 X: RelativeLayout.XConstraint="{Binding XC}"。还要添加到X's setter 另一行:OnPropertyChanged(nameof(XC));,因此 XAML 知道对 X 的任何更改也会更改 XC。
    猜你喜欢
    • 1970-01-01
    • 2014-05-14
    • 1970-01-01
    • 2011-08-23
    • 2019-04-28
    • 1970-01-01
    • 2017-11-10
    • 1970-01-01
    • 2014-11-12
    相关资源
    最近更新 更多