ListView的项目在WinRT中插入动画

时间:2012-12-31 00:28:09

标签: c# xaml windows-runtime winrt-xaml windows-store-apps

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

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

Here是拍摄的视频。

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

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

1 个答案:

答案 0 :(得分:18)

邮件应用程序是用JavaScript编写的,所以它不会帮助你知道它是如何完成的,因为这个UI堆栈与XAML堆栈完全不同。但事情是列表控件可能以相同的方式设置动画,因此您只需添加/删除列表中的某些项目即可获得扩展/折叠效果。

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

enter image description here

<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);
            }
        }
    }
}