【问题标题】:Bind Data from Bindablelayout.ItemTemplate in ViewModel in Xamarin在 Xamarin 的 ViewModel 中绑定来自 Bindablelayout.ItemTemplate 的数据
【发布时间】:2026-01-01 21:30:01
【问题描述】:

我在Dynamically adding Entry Controls 中遇到了一个问题,Wendy Zang - MSFT 帮助并解决了它。

从API获取条目列表的代码写在.xml.cs页面中,在.xml页面中,StackLayout的Bindablelayout.ItemTemplate用于设置条目模板

它运行良好,但提交表单的代码写在ViewModel

当我将.xml.cs 页面的代码粘贴到ViewModel 时,我无法获取条目,并且当代码在xml.cs 中时,我必须在ViewModel 中设置this.BindingContext = this; 代码没有执行。

.xml

<StackLayout BindableLayout.ItemsSource="{Binding forms}">
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <Entry Name="{Binding name}" Placeholder="{Binding label}" />
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</StackLayout>

xml.cs

RootObject list = JsonConvert.DeserializeObject<RootObject>(fields);

forms = new List<Form>();
forms = list.data.FirstOrDefault().Form.ToList();

this.BindingContext = this;

XAML 和 ViewModel 中的按钮

<Button
x:Name="SubmitButton"
Text="Submit"
Command="{Binding FormCommand}">
public ICommand FormCommand=> new Command(async (x) => await FormButton(default, default));

更新

从服务器获取动态字段的代码。

public async Task CreateCollection()
{
    Uri uri = new Uri(string.Format("http://example.com/entry"));

    HttpClient httpClient = new HttpClient(new NativeMessageHandler());

    HttpResponseMessage response = await httpClient.GetAsync(uri);
    string entries = await response.Content.ReadAsStringAsync();

    RootObject list = JsonConvert.DeserializeObject<RootObject>(entries);

    form = new List<Form>();
    form = list.data.FirstOrDefault().form.ToList();
}

【问题讨论】:

  • 您的 xaml 文件中有 &lt;ContentPage.Content&gt; 吗?如果是这样,应该是this.Content.BindingContent = this;
  • @Shaw 感谢您的回复,我使用了这个但仍然无法在ViewModel 中提交表单(我从.xml 页面和ViewModel 发布了按钮代码示例).. 如果有在xml.cs中不是this.Content.BindingContent = this;,那么它是可点击的,否则它不是
  • 如果我在ViewModel 中粘贴xml.cs 代码(从api 获取条目),则无法查看条目..
  • 去掉“x”,改成async () =&gt; 。如果列表绑定没问题,继续使用之前的绑定代码。
  • @Shaw 我尝试了 Wendy 的解决方案,当应用程序处于调试模式时,我刷新 .xml 页面,出现表单,否则它不会在第一次出现页面时出现.. 任何想法为什么会这样?

标签: c# .net xml xamarin xamarin.forms


【解决方案1】:

如果你想用 ViewModel 做这个,你可以参考下面的代码。

Xaml:

      <StackLayout>
        <Button
    x:Name="SubmitButton"
    Text="Submit"
    Command="{Binding FormCommand}"></Button>
        <StackLayout x:Name="DynamicEntry" BindableLayout.ItemsSource="{Binding forms}">
            <BindableLayout.ItemTemplate>
                <DataTemplate>
                    <Entry Placeholder="{Binding label}" MaxLength="{Binding max_length}" />

                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </StackLayout>
    </StackLayout>

后面的代码:

public partial class MainPage : ContentPage
{

    public MainPage()
    {
        InitializeComponent();

        this.BindingContext = new ViewModel();
    }
}

视图模型:

public class ViewModel
{
    public List<Form> forms { get; set; }
    public ICommand FormCommand { get; set; }
    public ViewModel()
    {
        CreateCollection();
        FormCommand = new Command(async (x) => await FormButton(default, default));
    }

    private Task FormButton(object p1, object p2)
    {
        return Task.Delay(2000);
    }

    public void CreateCollection()
    {
        var json = @"{
'success': 'true',
'data': [
{
    'form': [
        {
            'label': 'Name',
            'name': 'name',
            'type': 'text',
            'max_length': '15',
            'required': 'true'
        },
        {
            'label': 'Email',
            'name': 'email',
            'type': 'email',
            'max_length': '30',
            'required': 'true'
        }
    ]
}
]
}";
        var list = JsonConvert.DeserializeObject<Rootobject>(json);

        forms = new List<Form>();
        forms = list.data.FirstOrDefault().form.ToList();
    }
}

输出:

【讨论】:

  • 嗨,我使用了静态 JSON 条目,它工作正常,但是当我从 api 获取条目时,无法在视图中获取它(虽然我可以从 api 获取条目)。
  • 当应用程序处于调试模式时,我刷新.xml 页面,出现表单..为什么会这样?以及如何解决这个问题?
  • 我创建了CreateCollection() 函数,包括voidasync 并且还在MainThread.BeginInvokeOnMainThreadDevice.BeginInvokeOnMainThread 中编写了api 调用/响应。但仍然没有显示页面出现时表单,但是当我刷新.xml页面时(当它处于调试模式时,与PC连接时),它出现...
  • @Stavrogin 1. 尝试在OnAppearing 中调用CreateCollection() 方法而不是构造函数。 2.尽量用ObservableCollection&lt;Form&gt; Forms代替list
  • OnAppearing 中调用CreateCollection() 方法没有任何区别,我使用了ObservableCollection&lt;Form&gt; Forms 但在list.data.FirstOrDefault().form.ToList(); 上它说无法转换'System.Collection.Generic.List' 到 'System.Collections.ObjectModel.ObservableCollection'
【解决方案2】:

要全面了解,请查看@Wendy's 解决方案。问题是,打开页面时表单没有出现,但是当我处于调试模式并刷新 .xml 页面时,它出现了。

@Shaw 建议使用ObservableCollection&lt;&gt; 而不是List&lt;&gt;,但在list.data.FirstOrDefault().form.ToList(); 上它说无法将'System.Collection.Generic.List' 转换为'System.Collections.ObjectModel.ObservableCollection '.

我修好了..这是完整的解决方案。

private ObservableCollection<Form> _forms = new ObservableCollection<Form>();
public ObservableCollection<Form> Forms
{
    get
    {
        return _forms;
    }
    set
    {
        this.RaiseAndSetIfChanged(ref _forms, value);
    }
}
var list = JsonConvert.DeserializeObject<Rootobject>(json);

foreach (var i in list.data.Where(c => c.id == ""))
{
    _forms.Add(i.form.ToList());
}

【讨论】:

  • 如果form = list.data.FirstOrDefault().form.ToList(); 以前有效,您应该可以改用form = new ObservableCollection&lt;Form&gt;(list.data.FirstOrDefault().form);。但是我不太确定list.data.FirstOrDefault().form的类型