Xamarin Forms MVVM Stacklayout内容绑定

3
我很新于Xamarin和Xamarin Forms,需要一些帮助。
我有一个StackLayout,我想从我的ViewModel动态添加项目。但问题是我好像无法将StackLayout的内容绑定到我的ViewModel的StackLayout上。
这是我的视图中XAML代码:
<StackLayout/>

我希望你能够提供类似的东西

<StackLayout Content="{Binding MainStackLayout}"/>

我已经在我的ViewModel中设置了一个StackLayout,就像这样:

public StackLayout MainStackLayout;
3个回答

13

你需要编写一个UI组件。

using Xamarin.Forms;

using System.Collections.Specialized;
using System.ComponentModel;

class BindableStackLayout : StackLayout
{
    public static readonly BindableProperty ItemsProperty =
        BindableProperty.Create(nameof(Items), typeof(ObservableCollection<View>), typeof(BindableStackLayout), null,
            propertyChanged: (b, o, n) =>
            {
                (n as ObservableCollection<View>).CollectionChanged += (coll, arg) =>
                {
                    switch (arg.Action)
                    {
                        case NotifyCollectionChangedAction.Add:
                            foreach (var v in arg.NewItems)
                                (b as BindableStackLayout).Children.Add((View)v);
                            break;
                        case NotifyCollectionChangedAction.Remove:
                            foreach (var v in arg.NewItems)
                                (b as BindableStackLayout).Children.Remove((View)v);
                            break;
                        case NotifyCollectionChangedAction.Move:
                            //Do your stuff
                            break;
                        case NotifyCollectionChangedAction.Replace:
                            //Do your stuff
                            break;
                    }
                };
            });


    public ObservableCollection<View> Items
    {
        get { return (ObservableCollection<View>)GetValue(ItemsProperty); }
        set { SetValue(ItemsProperty, value); }
    }
}

我真的很困惑,我应该如何在XAML中使用这个? - Tarek Adel
1
`xmlns:local="clr-namespace:yourNamespace;assembly=yourAssembly"<local:BindableStackLayout Items="{Binding YourItemCollection}" />` - eakgul
一个小问题。"YourItemCollection"是什么类型?我的意思是它绑定到另一个StackLayout还是一个包含项目的字典? - Tarek Adel
没事了,我已经搞定了。非常感谢你,你救了我的一天! - Tarek Adel
嗨!@TarekAdel,你能分享一下你是如何解决这个问题的吗?我正在尝试动态地向StackLayout添加UI元素。 - lakvin
@lakvin,“YourItemCollection”是ObservableCollection吗?我用这段代码无法在我的UI中看到更新。 - Carlos Rodrigez

3

1

想要为您的StackLayout设置可绑定的ItemSource,并且具有不同的大小,我制作了自定义ContentView来帮助您实现它 :)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Xamarin.Forms;
/*
this class will help you to have bindable children with different sizes for the stacklayout with scrollview 
in you xaml add 
    <UIControls:SAStackLayout ItemsSource="{Binding YourDataSource}"  Orientation="Horizontal">
                            <DataTemplate>
                                <Grid>
                                    <Label Text="{Binding Name}" Margin="15,0" HorizontalOptions="Center" VerticalOptions="Center"    FontSize="Small"  VerticalTextAlignment="Center" HorizontalTextAlignment="Center" TextColor="White"/>
                                </Grid>
                            </DataTemplate>
   </UIControls:SAStackLayout>

 */
namespace Shop.UI.Controls
{
    [ContentProperty("ItemContent")]
    public class SAStackLayout : ContentView
    {
        private ScrollView _scrollview;
        private StackLayout _stacklayout { get; set; }
        public SAStackLayout()
        {
            _stacklayout = new StackLayout();
            _scrollview = new ScrollView()
            {
                Content = _stacklayout
            };
            Content = _scrollview;
        }
        public static readonly BindableProperty ItemContentProperty = BindableProperty.Create("ItemContent", typeof(DataTemplate), typeof(SAStackLayout), default(ElementTemplate));

        public DataTemplate ItemContent
        {
            get { return (DataTemplate)GetValue(ItemContentProperty); }
            set { SetValue(ItemContentProperty, value); }
        }


        private ScrollOrientation _scrollOrientation;
        public ScrollOrientation Orientation
        {
            get
            {
                return _scrollOrientation;
            }
            set
            {
                _scrollOrientation = value;
                _stacklayout.Orientation = value == ScrollOrientation.Horizontal ? StackOrientation.Horizontal : StackOrientation.Vertical;
                _scrollview.Orientation = value;
            }
        }

        public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(SAStackLayout), default(IEnumerable), propertyChanged: GetEnumerator);
        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        private static void GetEnumerator(BindableObject bindable, object oldValue, object newValue)
        {
            foreach (object child in (newValue as IEnumerable))
            {
                View view = (View)(bindable as SAStackLayout).ItemContent.CreateContent();
                view.BindingContext = child;
                (bindable as SAStackLayout)._stacklayout.Children.Add(view);
            }
        }
    }
}

这里下载源代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接