Xamarin 形成 MVVM Stacklayout 内容绑定

Posted

技术标签:

【中文标题】Xamarin 形成 MVVM Stacklayout 内容绑定【英文标题】:Xamarin forms MVVM Stacklayout content binding 【发布时间】:2017-05-10 09:30:43 【问题描述】:

我对 Xamarin 和 Xamarin 表单非常陌生,我需要一些帮助。

我有一个 StackLayout,我想从我的 ViewModel 中动态添加项目。问题是我似乎无法将 StackLayout 的内容绑定到我的 ViewModel 的 StackLayout。

这是我认为的 xaml 代码

<StackLayout/>

我想要类似的东西

<StackLayout Content="Binding MainStackLayout"/>

我的 ViewModel 中已经像这样设置了 StackLayout

public StackLayout MainStackLayout;

【问题讨论】:

【参考方案1】:

你必须编写一个 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 中使用它 xmlns:local="clr-namespace:yourNamespace;assembly=yourAssembly" &lt;local:BindableStackLayout Items="Binding YourItemCollection" /&gt; 一个小问题。 “YourItemCollection”是什么类型的?我的意思是它是否绑定到另一个 StackLayout 或 A Dictionary of items 没关系,我让它工作了。非常感谢你拯救了我的一天! 嘿! @TarekAdel,您能否分享有关您如何解决此问题的更多详细信息?我正在尝试将 UI 元素动态添加到 stackLayout。【参考方案2】:

只需使用 BindableLayout:https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/bindable-layouts

<StackLayout BindableLayout.ItemsSource="Binding Items">
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <Label Text="Binding Title" />
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</StackLayout>

它支持ItemsSource、ItemTemplate和ItemTemplateSelector。

【讨论】:

【参考方案3】:

想要为您的 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);
            
        
    

从here下载源码

【讨论】:

以上是关于Xamarin 形成 MVVM Stacklayout 内容绑定的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.forms MVVM。列表视图仍然为空

Xamarin 中的 MVVM 绑定

有没有办法在 Xamarin C# 中的 ListView 的列上方创建列名

Xamarin 条目绑定到 MVVM

在 Xamarin.Forms 项目中实现 MVVM

Xamarin MVVM 处理文件