我目前正在学习 .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();
}
}
}
如果这是一个基本问题,我很抱歉,但我完全陷入困境。
感谢您的帮助!
您在标签中看不到任何文本的原因是它不是属性。您需要使用 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;
}
}
您只能绑定到公共属性
这不是财产
public String s = "Hello world";
这是
public String s { get; } = "Hello world";