从 ViewModel 绑定标签文本不起作用

问题描述 投票:0回答:2

我目前正在学习 .NET MAUI,并且遇到了数据绑定问题。我已阅读 Microsoft 文档上有关数据绑定的部分,但我仍然不知道为什么它不起作用。

我可以显示按钮和第二个标签。但是,一旦我将它绑定到视图模型上的属性,它就不会显示。如果我使用 Binding .它显示 MauiTestApp.ViewModel.MainViewModel。我可以从中了解到的是数据上下文是正确的,并且我应该能够访问该属性。

这是我的视图模型:

using MauiTestApp.Model;
using System.Collections.ObjectModel;

namespace MauiTestApp.ViewModel
{
    public partial class MainViewModel : ObservableObject
    {
        public ObservableCollection<Monkey> Monkeys = new ObservableCollection<Monkey>();
        public String s = "Hello world";
        public MainViewModel()
        {
            Monkeys.Add(new Monkey("Bob", 20));
            Monkeys.Add(new Monkey("Steve", 10));
            Monkeys.Add(new Monkey("Joey", 14));
        }
    
        public void AddMonkey()
        {
            Monkeys.Add(new Monkey("Harry", 23));
        }
    }
}

这是 XAML

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MauiTestApp"
             xmlns:viewModel="clr-namespace:MauiTestApp.ViewModel"
             xmlns:model="clr-namespace:MauiTestApp.Model"
             x:Class="MauiTestApp.MainPage">
    <ContentPage.BindingContext>
        <viewModel:MainViewModel/>
    </ContentPage.BindingContext>
    
    <ScrollView>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="50"></RowDefinition>
                <RowDefinition Height="30"></RowDefinition>
                <RowDefinition Height="30"></RowDefinition>
            </Grid.RowDefinitions>
            <Button Grid.Row="0" Text="Press me" Pressed="Button_Pressed"></Button>
            <Label Grid.Row="1" Text="{Binding s}" TextColor="Purple" ></Label>
            <Label Grid.Row="2" Text="Hello world" TextColor="Purple"></Label>
    </ScrollView>

</ContentPage>

以及背后的XAML代码:

namespace MauiTestApp
{
    public partial class MainPage : ContentPage
    {
        public MainViewModel viewModel;
        public MainPage(MainViewModel vm)
        {
            InitializeComponent();
            viewModel = vm;
        }

        private void Button_Pressed(object sender, EventArgs e)
        {
             viewModel.AddMonkey();
        }
    }
}

如果这是一个基本问题,我很抱歉,但我完全陷入困境。

感谢您的帮助!

xaml data-binding binding maui datacontext
2个回答
1
投票

您在标签中看不到任何文本的原因是它不是属性。您需要使用 MVVM Toolkit 来让您的生活更轻松。阅读更多这里

所以 ViewModel 中的绑定应该如下所示

[ObservableProperty]
private string s = "Hello world";

并不是说它是带有小s的私有字段。通过 ObservableProperty,它被生成为一个适当的属性,该属性是公共的,并使用大写 S 进行分配。始终这样做很重要。切勿使用私有字段。始终是财产。

现在您的代码总体上存在很多问题,因此如果您不介意,我将为您提供一个可能的解决方案,以便我可以从您的代码中翻译出内容。我希望它有帮助。

首先,您的完整视图模型可以如下所示。注意 Method

[RelayCommand]
。它将采用您的方法并将其变成可绑定的命令。它还遵循命名约定。所以它绝不能以命令结束。为了绑定到它,我们在视图中添加 Command。通过这样做,我们将视图模型与对 MUAI 引用的所有引用解耦。

public partial class MonkeyViewModel : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<Monkey> _monkeys;

    [ObservableProperty]
    private string s = "Hello world";

    public MonkeyViewModel()
    {
        Monkeys = new()
        {
            new Monkey
            {
                Name = "Bob",
                Location = 20
            },
            new Monkey
                              {
                Name = "Steve",
                Location = 10
                },
            new Monkey
            {
                Name = "Joey",
                Location = 14
            },
        };
    }

    [RelayCommand]
    public void AddMonkey()
    {
        var harryMonkey = new Monkey
        {
            Name = "Harry",
            Location = 23
        };

        Monkeys.Add(harryMonkey);
    }
}

如果我们看看你的观点。它可能看起来像这样,显示金钱和按钮的列表。

<VerticalStackLayout>
    <CollectionView EmptyView = "No data" ItemsSource="{Binding Monkeys}">
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="models:Monkey">
                <Grid Padding = "10">
                    <Grid.RowDefinitions>
                        <RowDefinition Height = "*" />
                        <RowDefinition Height = "*" />
                        <RowDefinition Height = "Auto" />
                    </Grid.RowDefinitions>
                    <Label Grid.Row="0" Text="{Binding Name}" />
                    <Label Grid.Row="1" Text= "{Binding Location}" />
                    <BoxView
                        Grid.Row= "2"
                        BackgroundColor= "Gray"
                        HeightRequest= "1" />
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
    <Button
        Command= "{Binding AddMonkeyCommand}"
        Text= "Press me" />
    <Label
        Text= "{Binding S}"
        TextColor= "Purple" />

</VerticalStackLayout>

代码隐藏。永远不要忘记绑定到你的

BindingContext
,无论是在这里还是像你一样,在 xaml 中。如果不是,您的视图将不会绑定到任何东西。

public partial class MainPage : ContentPage
{
    private readonly MonkeyViewModel _monkeyViewModel;
    public MainPage(MonkeyViewModel monkeyViewModel)
    {
        _monkeyViewModel = monkeyViewModel;
        InitializeComponent();
        BindingContext = _monkeyViewModel;
    }
}

1
投票

您只能绑定到公共属性

这不是财产

public String s = "Hello world";

这是

public String s { get; } = "Hello world";
© www.soinside.com 2019 - 2024. All rights reserved.