我正在开发一个项目,它类似于在 maui 社区工具包的帮助下使用 MVVM 方案的购物车。我有一个可观察集合中的项目列表,点击/单击它们后,我将它们添加到一个单独的可观察集合中,我们将其称为购物车。对于购物车中的每个商品,我想显示商品的名称和商品的数量。默认情况下,它设置为 1,并且显示金额并限制为一个条目。我还有一个步进器控件,它的值也限制为该金额值,这样用户如果只想增加几个,则不必键入,如果他们想添加,也不必单击太多次喜欢 20 个项目。这一切都在此代码片段中完成:
<CollectionView
Grid.Column="0"
ItemsSource="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:InvoiceViewModel}}, Path=ItemsSold}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:ItemSold">
<Grid
ColumnDefinitions="*,*,80">
<Label
HorizontalOptions="Start"
VerticalOptions="Center"
Grid.Column="0"
Style="{StaticResource DefaultLabelStyle}"
Text="{Binding name}"/>
<Entry
HorizontalOptions="Start"
VerticalOptions="Center"
WidthRequest="150"
Grid.Column="1"
BackgroundColor="White"
Text="{Binding amount}"/>
<Stepper
Grid.Column="2"
Value="{Binding amount}"
Increment="1"
Minimum="0"
Maximum="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:InvoiceViewModel}}, Path=inf}"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
我有一个按钮,单击该按钮会显示该项目的数量,以便我可以调试一些代码。当我在条目中键入一个值(例如 5)并单击按钮时,它显示金额为 5。如果我单击步进器中的增加按钮并单击按钮,它显示 2,默认值 1 + 1,从中我看到有是 amount 变量的两个实例,这不是我想要的。我希望输入控件和步进控件能够同时相互更新,同时也更新绑定数据。 在我的视图模型中,这就是我所拥有的:
public ObservableCollection<Item> Items { get; set; } = new();
public ObservableCollection<ItemSold> ItemsSold { get; set; } = new();
public int inf = int.MaxValue;
public InvoiceViewModel() { }
public async Task GetItems()
{
await InventoryService.Init();
try
{
var items = await InventoryService.GetItems();
if (Items.Count != 0) { Items.Clear(); }
foreach (var item in items)
{
Items.Add(item);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
await Shell.Current.DisplayAlert("Error", "Unable to fetch inventory \n" + ex.Message, "OK");
}
}
[RelayCommand]
private void AddToInvoice(Item item)
{
if (item.unitPrice is null) { return; }
ItemSold itemSold = new();
itemSold.name = item.name;
itemSold.description = item.description;
itemSold.unitName = item.unitName;
itemSold.unitPrice = (double)item.unitPrice;
itemSold.amount = 1;
ItemsSold.Add(itemSold);
}
我尝试过将双向绑定模式添加到仅条目、仅步进器以及两者,但都没有解决问题。由于在手势点击完成之前条目和步进器不存在,因此我无法在视图模型中创建属性并使用 maui 社区工具包中的可观察属性标签对其进行标记。将金额数据绑定到条目和步进器以便它们始终共享相同的值时,我缺少什么?
您可以使用 MVVM Toolkit 来实现这一点。
您可以尝试为 public int amount
添加
ObservableProperty属性(
ItemSold.cs
)。然后它会生成一个可观察的属性Amount
。
如果更改 Amount
的值,UI 将自行更新(包括 Entry
和 Stepper
)。
public partial class ItemSold:ObservableObject
{
public string name { get; set; }
[ObservableProperty]
public int amount;
}
然后在
InvoiceViewModel.cs
中,我为ItemsSold
添加了一些假数据。
public partial class InvoiceViewModel: ObservableObject
{
public ObservableCollection<ItemSold> ItemsSold { get; set; } = new ObservableCollection<ItemSold>();
public int inf = int.MaxValue;
public ICommand GetCommand { get; set; }
public InvoiceViewModel() {
ItemsSold.Add(new ItemSold { name ="Name 1",Amount = 1});
ItemsSold.Add(new ItemSold { name ="Name 2", Amount = 1});
ItemsSold.Add(new ItemSold { name ="Name 3", Amount = 1});
}
[RelayCommand]
private void GetResult()
{
foreach (var item in ItemsSold)
{
System.Diagnostics.Debug.WriteLine("------- item's name is: " + item.name +"<---> count is : " + item.Amount);
}
}
}
最后,我们需要为Entry和
Amount
绑定生成的属性Stepper
。
例如:
<?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"
x:Class="MauiCheckListviewApp.Views.SharedNumberPage"
xmlns:viewmodel ="clr-namespace:MauiCheckListviewApp.ViewModes"
xmlns:model ="clr-namespace:MauiCheckListviewApp.Models"
Title="SharedNumberPage">
<ContentPage.BindingContext>
<viewmodel:InvoiceViewModel></viewmodel:InvoiceViewModel>
</ContentPage.BindingContext>
<VerticalStackLayout>
<CollectionView Grid.Column="0" ItemsSource="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:InvoiceViewModel}}, Path=ItemsSold}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:ItemSold">
<Grid
ColumnDefinitions="*,*,80">
<Label
HorizontalOptions="Start"
VerticalOptions="Center"
Grid.Column="0"
Text="{Binding name}"/>
<Entry
HorizontalOptions="Start"
VerticalOptions="Center"
WidthRequest="150"
Grid.Column="1"
BackgroundColor="White"
Text="{Binding Amount}"/>
<Stepper
Grid.Column="2"
Value="{Binding Amount}"
Increment="1"
Minimum="0"
Maximum="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:InvoiceViewModel}}, Path=inf}"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Button Text="get result" Command="{Binding GetResultCommand}"/>
</VerticalStackLayout>
</ContentPage>
注:
我还添加了一个按钮来获取
ItemsSold
的最后结果来验证数字,结果也符合我们的预期:Entry和Stepper共享相同的数量。