Xamarin.Forms(XAML):根据条件不同的布局

时间:2017-05-09 12:20:49

标签: xaml xamarin.forms

有没有办法根据一个条件选择初始化的布局?我有一个足球统计数据,但如果myViewModel.Sport == Sports.Basketball我想加载完全不同的布局。

我在每个视图中使用 Datatrigger 尝试过类似的内容,但对我来说这似乎很麻烦:

<Label Text="{Binding Goals}" 
       Grid.Row="1" Grid.Column="0">
    <Label.Triggers>
        <DataTrigger TargetType="Label" 
                     Binding="{Binding Sport}" 
                     Value="1">
            <Setter Property="Text" 
                    Value="{Binding Points}"/>
        </DataTrigger>
    </Label.Triggers>
</Label>

我显示“目标”,但如果体育枚举值为1(Sports.Basketball),我会改为“点数”。我想用大量标签甚至图像来做这个,所以我需要一个合适的方法来做到这一点。

有人可以帮助我吗?我需要根据我的ViewModel的Sport属性加载不同的Grid。

2 个答案:

答案 0 :(得分:4)

您可以做的另一件事是将每个单独的运动放入其自己的视图中,将所有视图添加到您的页面并根据您想要显示的运动设置其IsVisible属性。

一个例子在伪代码中看起来像这样:

<Page>
   <Grid>
       <BasketballView IsVisible="{Binding IsBasketball}">
       <SoccerView IsVisible="{Binding IsSoccer}">
       <FootballView IsVisible="{Binding IsFootball}">
   </Grid>
</Page>

然后从ViewModel中设置适当的布尔值。

答案 1 :(得分:0)

要使用DataTemplateSelector解决此问题,如@StephaneDelcroix所述,您需要一个具有ItemsSourceItemTemplate属性的自定义类。

我还没有考虑/测试过如何将DataTemplateSelector与此结合使用;欢迎任何人将其添加到此答案中。

using System.Collections;
using Xamarin.Forms;

namespace YourNamespace
{
    // From https://forums.xamarin.com/discussion/19874/listview-inside-stacklayout-a-height-problem/p2, @maxx313.
    public class TemplatedStack : StackLayout
    {
        public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create("ItemsSource", typeof(IList), typeof(TemplatedStack), propertyChanged: OnItemsSourceChanged);
        public IList ItemsSource
        {
            get { return (IList)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }
        private static void OnItemsSourceChanged(BindableObject pObj, object pOldVal, object pNewVal)
        {
            var layout = pObj as TemplatedStack;

            if (layout != null && layout.ItemTemplate != null)
            {
                layout.BuildLayout();
                layout.ForceLayout();
            }
        }

        public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(TemplatedStack), propertyChanged: OnItemTemplateChanged);
        public DataTemplate ItemTemplate
        {
            get { return (DataTemplate)GetValue(ItemTemplateProperty); }
            set { SetValue(ItemTemplateProperty, value); }
        }
        private static void OnItemTemplateChanged(BindableObject pObj, object pOldVal, object pNewVal)
        {
            var layout = pObj as TemplatedStack;

            if (layout != null && layout.ItemsSource != null)
                layout.BuildLayout();
        }



        private void BuildLayout()
        {
            Children.Clear();

            foreach (var item in ItemsSource)
            {
                var view = (View)ItemTemplate.CreateContent();
                view.BindingContext = item;
                Children.Add(view);
            }
        }

        protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
        {
            return base.OnMeasure(widthConstraint, heightConstraint);
        }
    }
}

在您的XAML中,

<yourXmlns:TemplatedStack .../>

其中yourXmlns必须是XAML顶部的xmlns声明。

ItemsSourceItemTemplate属性的用法类似于将项目集合和模板绑定到ListView的方式。
(此处不使用ListView的原因是ListView可能会干扰触摸事件,并增加额外的布局成本。)

为此绑定一个包含单个项目的集合。
例如。对于这个问题,该项目将是正在查看的特定运动。