MAUI使用MVVM向GUI添加控制元素



我在当前的MAUI项目中使用社区工具MVVM。我想动态地添加控件,如运行时期间的GUI入口。我想从ViewModel中做到这一点。使用该工具包,提供函数和属性并与之交互当然非常容易。不幸的是,我还没有找到一种方法来直接访问StackLayout或类似的东西。

我试着给垂直stacklayout属性x:name(在我的xaml文档)一个名字,然后访问它。这可以从代码后面工作,但不能从ViewModel本身。

我期望在viewModel中显示,例如我的StackLayout,然后我可以执行以下操作。

stackLayout.Add(new Label { Text = "Primary colors" }));

此外,我还尝试为属性x:name提供一个绑定。x:Name="{Binding StackLayout}

在ViewModel中,我试着提供这个属性。

[ObservableProperty]
VerticalStackLayout stackLayout;

澄清一下:ViewModel不知道View,但是View知道ViewModel。

因此,视图后面的代码可以做需要做的事情。

  • 如果视图没有一个属性来保存视图模型,那么在后面添加代码:
private MyVM VM => (MyVM)BindingContext;

定义了一个VM属性,所以你可以做VM.MyDictionary[someKey]或类似的。

  • 如果在设置BindingContext之前需要在构造器中访问VM,然后编辑问题,显示BindingContext当前是如何设置的。

是的,您可以使用MVVM来实现这一点。

一个简单的方法是使用Bindable Layouts来实现这一点。

请参考以下代码:

1。为当前页面创建视图模型

MyViewModel.cs

public class MyViewModel 
{
public int index = 0;
public ObservableCollection<Data> Items { get; set; }
public ICommand AddItemCommand => new Command(addItemMethod);
private void addItemMethod(object obj)
{
index++;
Items.Add(new Data { FileName ="File " + index});
}

public MyViewModel()
{
Items = new ObservableCollection<Data>();
}
}

Data.cs

public class Data 
{
public string FileName { get; set; }
}

2. mainpage.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:mauiapp="clr-namespace:MauiAddViewApp116"
x:Class="MauiAddViewApp116.MainPage"
x:Name="mainpage"
>
<ContentPage.BindingContext>
<mauiapp:MyViewModel></mauiapp:MyViewModel>
</ContentPage.BindingContext>
<ScrollView>
<VerticalStackLayout 
Margin="10"
VerticalOptions="StartAndExpand">
<Button Text="Add item" Command="{Binding AddItemCommand}"></Button>
<StackLayout BindableLayout.ItemsSource="{Binding Items}" Orientation="Vertical">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Label   HorizontalOptions="Fill" Text="{Binding FileName}" FontSize="Large" HeightRequest="38" />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</VerticalStackLayout>
</ScrollView>
</ContentPage>

首先,我想回答的是,没有什么是阻止你从传递你的StackLayout作为CommandParameter的引用到ViewModel中的命令。写这:

[RelayCommand]    
void Add(StackLayout myLayout)...

在XAML中传递引用。

然而,很少有情况可以证明这一点。这些情况都不能"自定义gui"。

你需要学习如何使用DataTemplates, DataTriggers, Styles, EventToCommandBehaviors, Gestures, ControlTemplates, Validators和ValueConvertors。

这将涵盖访问View及其元素的基本需求。

我已经找到解决问题的办法了。

如你所建议的,我已经把它放了。我使用视图的后台代码来访问StackLayout。

1。MainPage.xaml

<ScrollView>
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center"
x:Name="VStackLayout">
</VerticalStackLayout>
</ScrollView>

使用属性x:name,我可以从后面的代码访问VS布局。

2。MainPage.xaml.cs

Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();        
public MainPage(MainPageViewModel viewModel)
{
InitializeComponent();
BindingContext = viewModel;
foreach (var item in viewModel.KeyValues)
{

if (item.Value == "String")
{
keyValuePairs.Add(item.Key, "");
var entry = new Entry {
Placeholder = item.Key,
ClassId = item.Key,
Text = (String)keyValuePairs.Where(k => k.Key == item.Key).First().Value

};
VStackLayout.Add(entry);
}
else if (item.Value == "Boolean")
{
keyValuePairs.Add(item.Key, true);
Label label = new Label { Text = item.Key};
var toogle = new Switch
{
IsEnabled = true,
ClassId = item.Key,
IsToggled = (Boolean)keyValuePairs.Where(k => k.Key == item.Key).First().Value

};
HorizontalStackLayout views = new HorizontalStackLayout();
views.HorizontalOptions = LayoutOptions.StartAndExpand;
views.VerticalOptions = LayoutOptions.Center;
views.Add(label);
views.Add(toogle);
VStackLayout.Add(views);
}

}

在这里访问ViewModel中的Dic,然后从它创建GUI。

不幸的是,对元素(条目)内容的访问还不能工作。我想看看如何在字典里写内容。此时绑定还不起作用。有人知道吗?

最新更新