将 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详解