【问题标题】:Xamarin.Forms (XAML): Different layouts depending on a conditionXamarin.Forms (XAML):根据条件不同的布局
【发布时间】:2017-05-09 12:20:49
【问题描述】:

有没有办法根据一个条件选择什么布局初始化?我有一个足球统计数据网格,但如果 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>

我显示“目标”,但如果 Sports 枚举值为 1(Sports.Basketball),我将更改为“点数”。我想用很多标签甚至图像来做到这一点,所以我需要一种正确的方法来做到这一点。

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

【问题讨论】:

  • 为什么不完全推送一个完全不同的页面?
  • @Gerald 我的页面是 TabbedPage 的一部分。我认为它不应该起作用,不是吗?
  • 您可以做的另一件事是将每个单独的运动放入它自己的视图中,将所有视图添加到您的页面并根据您要显示的运动设置它们的IsVisible 属性
  • 感谢@Gerald,它对我来说很好用!我为每项运动创建了一个网格,并根据枚举值管理它们的可见性。
  • 我会使用 DataTemplateSelector

标签: xaml xamarin.forms


【解决方案1】:

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

伪代码示例如下:

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

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

【讨论】:

  • 那可能很贵。即使不可见,也可能会创建视图。
  • @StephaneDelcroix - 如果我理解正确,它们是创建的,但没有布局调用。当不可见时,即使对于复杂的布局,我也没有注意到明显的延迟(鉴于已编译的 XAML 和 AOT)。 [然而,任何尝试这种技术的人,如果他们在发布版本中出现页面之前出现明显的延迟,应该在完全移除不可见视图的情况下再次测试,看看这是否是延迟的原因。]
  • @StephaneDelcroix - 啊,我没有阅读您对问题的评论,请改用DataTemplateSelector。是的,我认为这是更好的方法。 (虽然我遇到过更复杂的情况,在布局的某些部分使用 IsVisible 比弄清楚如何使用 DataTemplateSelectors 更容易。)
【解决方案2】:

如@StephaneDelcroix 所述,要使用DataTemplateSelector 解决此问题,您需要一个具有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 可能会干扰触摸事件,并增加额外的布局成本。)

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

【讨论】:

    猜你喜欢
    • 2021-02-22
    • 1970-01-01
    • 1970-01-01
    • 2017-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多