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