将 StackLayout 绑定到 ViewModel 不起作用

Posted

技术标签:

【中文标题】将 StackLayout 绑定到 ViewModel 不起作用【英文标题】:Binding StackLayout to ViewModel doens't work 【发布时间】:2022-01-01 06:30:18 【问题描述】:

我想在我的 ViewModel 中有一个属性链接到我的 StackLayout。我通过将 StackLyout 绑定到 ViewModel 进行了尝试。

当我点击一个按钮时,这个布局应该是不可见的。

当我使用下面的代码执行此操作时,我的程序因 NulReferenceObject 崩溃:对象引用未设置为对象的实例。我所说的 StackLayout 是下面代码中的第一个。

<FlexLayout>
    <StackLayout BindableLayout.ItemTemplate="Binding CreateQuizPageQuizNameSL"> // This StackLayout should be bind to the ViewModel
        <Label Text="Create New Quiz" />
        <StackLayout >
            <Entry Text="Binding QuizNameInput" Placeholder="Enter quiz name"/>
        </StackLayout>
    </StackLayout>
    <Button Command="Binding SubmitCreateQuizCommand" Text="Create my quiz now!"></Button>
</FlexLayout>

视图模型

internal class CreateQuizPageViewModel

    // Quiz Name Input
    public String QuizNameInput  get; set; 

    // Command submit creating a quiz
    public Command SubmitCreateQuizCommand  get; set; 

    public StackLayout CreateQuizPageQuizNameSL  get; set;  = new StackLayout();

    public CreateQuizPageViewModel()
    
        // Declaring a new command, giving the OnSubmitCreateNewQuizClick to the delegate
        SubmitCreateQuizCommand = new Command(OnSubmitCreateNewQuizClick);
    

    // When a user submit the creation of new quiz
    public void OnSubmitCreateNewQuizClick()
    
        CreateQuizPageQuizNameSL.IsVisible = false;
    

【问题讨论】:

CreateQuizPageQuizNameSL 在您的虚拟机中声明但从未实例化,因此它始终为空。 @Jason 如果我将我的 StackLayout 初始化为一个新的 StackLayout (public StackLayout CreateQuizPageQuizNameSL get; set; = new StackLayout();),我不会崩溃,但这样我会丢失我的 StackLayout。正在创建一个我不想要的新实例。 它并不清楚你想要完成什么。在你的 VM 中拥有 View 对象违背了 MVVM 的想法。而且您似乎没有按预期使用 BindableLayouts。您通常定义一个模板并将其应用于布局的 ItemsSource 中的每个元素,您甚至没有使用它。如果您只想控制布局的可见性,您只需绑定IsVisible 属性 我想要完成的事情:当用户点击一个按钮时,follow 方法被执行:OnSubmitCreateNewQuizClick()。此方法应删除我尝试绑定的 StackLayout,以便将来用另一个 StackLayout 替换它。问题是 OnSubmitCreateNewQuizClick() 方法是在 VM 中执行的,所以我需要对 .xaml 文件中存在的 StackLayout 的引用,我目前没有 我建议让 VM 引发一个事件,然后视图会响应该事件以添加/修改/删除内容 【参考方案1】:

这里是如何使用IsVisible绑定切换两种布局。

首先将Nuget Xamarin.CommunityToolkit 添加到您的 Xamarin Forms 项目中。 (即“MyProjectName”,末尾没有“.ios”或“.android”。)

TwoLayoutPage.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:xct="http://xamarin.com/schemas/2020/toolkit"
                 xmlns:local="clr-namespace:TestBugs"
                 x:Class="TestBugs.TwoLayoutPage">
    <ContentPage.BindingContext>
        <local:TwoLayoutViewModel/>
    </ContentPage.BindingContext>
    <ContentPage.Resources>
        <ResourceDictionary>
            <xct:InvertedBoolConverter x:Key="InvertedBoolConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout>
            <StackLayout 
                    IsVisible="Binding UseSecondLayout, Converter=StaticResource InvertedBoolConverter"
                    VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
                <Label Text="First Layout" FontSize="20" />
                <Button Text="To Second" Command="Binding SwitchToSecondLayoutCommand" />
            </StackLayout>
            <StackLayout IsVisible="Binding UseSecondLayout"
                    VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
                <Label Text="Second Layout!" FontSize="32" />
            </StackLayout>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

TwoLayoutViewModel.cs:

using Xamarin.Forms;

namespace TestBugs

    public class TwoLayoutViewModel : BindableObject
    
        private bool _usesecondLayout = false;
        public bool UseSecondLayout 
            get => _usesecondLayout;
            set 
                _usesecondLayout = value;
                OnPropertyChanged();
            
        


        public TwoLayoutViewModel()
        
            SwitchToSecondLayoutCommand = new Command(SwitchToSecondLayout);
        


        public Command SwitchToSecondLayoutCommand  get; set; 


        private void SwitchToSecondLayout()
        
            UseSecondLayout = true;
        
    

【讨论】:

以上是关于将 StackLayout 绑定到 ViewModel 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Xamarin.iOS 将广告内容分配给 stacklayout

嵌套在水平 StackLayout 中时,多行标签不会调整父 StackLayout 的大小

xamarin forms常用的布局stacklayout详解

水平 StackLayout 中的 ListView - Nativescript Vue

HarmonyOS之常用布局StackLayout的使用

鸿蒙HarMonyOS之StackLayout布局的常用属性