4

最近我开始构建自己的大型 Windows 8 应用商店应用程序。在 UI 上工作,我开始复制一些好的 UI。

我遇到了一个非常有趣的动画,即在标准邮件应用程序的列表视图中插入新元素。当您单击链时,它会展开并显示链中的所有消息。

是捕获的视频。

我不知道他们使用什么技术来实现这个动画和行为。

任何人都可以帮助我,解释或举例我如何实现这种行为?谢谢。

4

1 回答 1

18

邮件应用程序是用 JavaScript 编写的,因此了解它是如何完成的对您没有多大帮助,因为此 UI 堆栈与 XAML 堆栈完全不同。但问题是列表控件可能以相同的方式进行动画处理,因此您只需要添加/删除列表中的一些项目即可获得展开/折叠效果。

我玩了一会儿,这就是我想出的,它使用 ListView 的 ItemTemplateSelector 属性来定义几个不同的项目模板。

在此处输入图像描述

<Page
    x:Class="App82.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App82"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.Resources>
        <local:CollapsibleListItemTemplateSelector
            x:Key="collapsibleListItemTemplateSelector">
            <local:CollapsibleListItemTemplateSelector.BasicItemTemplate>
                <DataTemplate>
                    <Border
                        Margin="5"
                        Height="50"
                        VerticalAlignment="Stretch"
                        BorderBrush="ForestGreen"
                        BorderThickness="2,0,0,0">
                        <StackPanel
                            Margin="10,0,0,0">
                            <TextBlock
                                FontWeight="Bold"
                                Text="{Binding Title}" />
                            <TextBlock
                                Text="{Binding Gist}" />
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </local:CollapsibleListItemTemplateSelector.BasicItemTemplate>
            <local:CollapsibleListItemTemplateSelector.ExpandedItemTemplate>
                <DataTemplate>
                    <Border
                        Margin="15,5,5,5"
                        Height="50"
                        VerticalAlignment="Stretch"
                        BorderBrush="Yellow"
                        BorderThickness="2,0,0,0">
                        <StackPanel
                            Margin="10,0,0,0">
                            <TextBlock
                                FontWeight="Bold"
                                Text="{Binding Title}" />
                            <TextBlock
                                Text="{Binding Gist}" />
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </local:CollapsibleListItemTemplateSelector.ExpandedItemTemplate>
            <local:CollapsibleListItemTemplateSelector.CollapsibleItemTemplate>
                <DataTemplate>
                    <Border
                        Margin="5"
                        Height="50"
                        VerticalAlignment="Stretch"
                        BorderBrush="DodgerBlue"
                        BorderThickness="2,0,0,0">
                        <StackPanel
                            Margin="10,0,0,0"
                            Orientation="Horizontal">
                            <TextBlock
                                FontWeight="Bold"
                                Text="{Binding ChildItems.Count}" />
                            <TextBlock
                                FontWeight="Bold"
                                Text="&#160;Items" />
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </local:CollapsibleListItemTemplateSelector.CollapsibleItemTemplate>
        </local:CollapsibleListItemTemplateSelector>
    </Page.Resources>
    <Grid
        Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <ListView
            x:Name="ListView"
            ItemTemplateSelector="{StaticResource collapsibleListItemTemplateSelector}"
            ItemClick="OnItemClick"
            IsItemClickEnabled="True" />
    </Grid>
</Page>

后面的代码:

using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using App82.Common;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace App82
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            var items = new ObservableCollection<BindableBase>();
            var item1 = new BasicItem { Title = "Item 1", Gist = "This item has some content that is not fully shown..." };
            var item2 = new ExpandedItem { Title = "Item 2", Gist = "This item has some content that is not fully shown..." };
            var item3 = new ExpandedItem { Title = "Item 3", Gist = "This item has some content that is not fully shown..." };
            var item4 = new ExpandedItem { Title = "Item 4", Gist = "This item has some content that is not fully shown..." };
            var item5 = new BasicItem { Title = "Item 5", Gist = "This item has some content that is not fully shown..." };

            var itemGroup1 = new CollapsibleItem(items, new[] { item2, item3, item4 });
            items.Add(item1);
            items.Add(itemGroup1);
            items.Add(item5);
            this.ListView.ItemsSource = items;
        }

        private void OnItemClick(object sender, ItemClickEventArgs e)
        {
            var collapsibleItem = e.ClickedItem as CollapsibleItem;
            if (collapsibleItem != null)
                collapsibleItem.ToggleCollapse();
        }
    }

    public class CollapsibleListItemTemplateSelector : DataTemplateSelector
    {
        public DataTemplate BasicItemTemplate { get; set; }
        public DataTemplate CollapsibleItemTemplate { get; set; }
        public DataTemplate ExpandedItemTemplate { get; set; }

        protected override Windows.UI.Xaml.DataTemplate SelectTemplateCore(object item, Windows.UI.Xaml.DependencyObject container)
        {
            if (item is ExpandedItem)
                return ExpandedItemTemplate;
            if (item is BasicItem)
                return BasicItemTemplate;
            //if (item is CollapsibleItem)
                return CollapsibleItemTemplate;
        }
    }

    public class BasicItem : BindableBase
    {
        #region Title
        private string _title;
        public string Title
        {
            get { return _title; }
            set { this.SetProperty(ref _title, value); }
        }
        #endregion

        #region Gist
        private string _gist;
        public string Gist
        {
            get { return _gist; }
            set { this.SetProperty(ref _gist, value); }
        }
        #endregion
    }

    public class ExpandedItem : BasicItem
    {

    }

    public class CollapsibleItem : BindableBase
    {
        private readonly IList _hostCollection;

        #region IsExpanded
        private bool _isExpanded;
        public bool IsExpanded
        {
            get { return _isExpanded; }
            set
            {
                if (this.SetProperty(ref _isExpanded, value))
                {
                    if (_isExpanded)
                        Expand();
                    else
                        Collapse();
                }
            }
        }
        #endregion

        #region ChildItems
        private ObservableCollection<BasicItem> _childItems;
        public ObservableCollection<BasicItem> ChildItems
        {
            get { return _childItems; }
            set { this.SetProperty(ref _childItems, value); }
        }
        #endregion

        public CollapsibleItem(
            IList hostCollection,
            IEnumerable<BasicItem> childItems)
        {
            _hostCollection = hostCollection;
            _childItems = new ObservableCollection<BasicItem>(childItems);
        }

        public void ToggleCollapse()
        {
            IsExpanded = !IsExpanded;
        }

        private void Expand()
        {
            int i = _hostCollection.IndexOf(this) + 1;

            foreach (var childItem in ChildItems)
            {
                _hostCollection.Insert(i++, childItem);
            }
        }

        private void Collapse()
        {
            int i = _hostCollection.IndexOf(this) + 1;

            for (int index = 0; index < ChildItems.Count; index++)
            {
                _hostCollection.RemoveAt(i);
            }
        }
    }
}
于 2012-12-31T06:53:45.880 回答