XAML MAUI使用MVVM将控制元素添加到GUI

hzbexzde  于 2023-01-18  发布在  其他
关注(0)|答案(4)|浏览(208)

我在我当前的MAUI项目中使用社区工具MVVM。我希望在运行时动态地添加控件,比如GUI的入口。我希望从ViewModel中完成。使用该工具包,提供函数和属性并与之交互当然非常容易。不幸的是,我还没有找到直接访问StackLayout或类似内容的方法。
我试着给VerticalStackLayout属性x:name(在我的xaml文档中)一个名称,然后访问它,这可以从代码隐藏中实现,但不能从ViewModel本身实现。
我希望在viewModel中显示我的StackLayout,然后我可以执行以下操作。
stackLayout.Add(new Label { Text = "Primary colors" }));
此外,我还尝试为属性x提供绑定:name.x:Name="{Binding StackLayout}
在ViewModel中,我尝试提供该属性。

[ObservableProperty]
VerticalStackLayout stackLayout;
5fjcxozz

5fjcxozz1#

澄清一下:视图模型不知道视图,但视图确实知道视图模型。
因此,视图背后的代码可以完成所需的工作。

  • 如果视图还没有保存视图模型的属性,则添加代码:
private MyVM VM => (MyVM)BindingContext;

它定义了一个VM属性,因此您可以执行VM.MyDictionary[someKey]或类似操作。

  • 如果您需要在设置BindingContext之前访问构造函数中的VM,请编辑问题,以显示当前如何设置BindingContext
tvmytwxo

tvmytwxo2#

是的,您可以使用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.主页. 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>
r1zhe5dt

r1zhe5dt3#

我已经找到了解决问题的办法。
正如您所建议的,我已经将其放置好了,我使用视图的代码隐藏来访问StackLayout。

1.主页.xaml

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

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

2.主页.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。
不幸的是,对元素(条目)内容的访问还不起作用,我想看看如何将内容写在字典中,此时的绑定还不起作用,有没有人有主意?

sauutmhj

sauutmhj4#

首先,我想回答的是,没有什么能阻止你将StackLayout的引用作为CommandParameter传递给ViewModel中的Command。

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

然后在XAML中传递引用。
然而,很少有情况能证明这一点,那些情况都不是“定制GUI”。
您需要学习如何使用数据模板、数据触发器、样式、事件到命令行为、手势、控件模板、验证器和值转换器。
这将涵盖您访问视图及其元素的基本需求。

相关问题