Xaml 弹出型按钮转换问题中的ListView

Xaml 弹出型按钮转换问题中的ListView,xaml,windows-phone-8,winrt-xaml,windows-phone-8.1,win-universal-app,Xaml,Windows Phone 8,Winrt Xaml,Windows Phone 8.1,Win Universal App,我在弹出按钮中使用分组的列表视图,当弹出窗口打开时,组标题出现奇怪的UI问题。这种情况只发生了一小部分秒,但大多数用户仍然注意到了这一点 XAML(摘自完整复制样本): 我不能使用内置的ListPickerFlyout,因为它不支持分组 我试图在列表视图/弹出按钮的默认样式中找到相应的故事板或转换,但未能找到 我想修复该动画或完全禁用它。非常感谢您的帮助。摆脱这种奇怪的动画错误的一种方法是首先运行弹出控件的动画,然后在动画完成后显示列表视图 为此,您需要在弹出按钮中订阅以下事件。您还需

我在
弹出按钮中使用分组的
列表视图
,当弹出窗口打开时,组标题出现奇怪的UI问题。这种情况只发生了一小部分秒,但大多数用户仍然注意到了这一点

XAML(摘自完整复制样本):


我不能使用内置的
ListPickerFlyout
,因为它不支持分组

我试图在
列表视图
/
弹出按钮
的默认样式中找到相应的故事板或转换,但未能找到


我想修复该动画或完全禁用它。非常感谢您的帮助。

摆脱这种奇怪的动画错误的一种方法是首先运行
弹出控件的动画,然后在动画完成后显示
列表视图

为此,您需要在
弹出按钮中订阅以下事件。您还需要为
列表视图
指定一个名称,并将其
不透明度
设置为
0

   <Flyout Opened="Flyout_Opened" Closed="Flyout_Closed">
       <ListView x:Name="MyListView" Opacity="0" ItemsSource="{Binding Source={StaticResource ItemsViewSource}}" Margin="20 0">
然而,在提供了一个可能的解决方案之后,我不认为使用
弹出控件来更改视觉样式是正确的方法

弹出按钮
控件不是为处理大量数据而设计的。它不支持虚拟化(我认为)。例如,如果您将项目数量从30增加到300,则一旦按下按钮,加载将花费相当多的时间

更新(包括工作样本)

我在想,也许我可以创建一个控件来处理所有这些,因为在一天结束时,您确实希望能够检索您在列表中单击的项目并关闭弹出窗口

不幸的是,
ListPickerFlyout
是密封的,所以我选择创建一个从
弹出按钮
继承的控件

这很直截了当。基本上,该控件公开诸如
ItemsSource
SelectedItem
等属性。它还订阅
ListView
ItemClick
事件,因此每当单击一个项时,它就会关闭
弹出按钮
,并填充
SelectedItem

public class ListViewFlyout : Flyout
{
    private ListView _listView;

    public object ItemsSource
    {
        get { return (object)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource", typeof(object), typeof(ListViewFlyout), new PropertyMetadata(null));

    public DataTemplate HeaderTemplate
    {
        get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
        set { SetValue(HeaderTemplateProperty, value); }
    }

    public static readonly DependencyProperty HeaderTemplateProperty =
        DependencyProperty.Register("HeaderTemplate", typeof(DataTemplate), typeof(ListViewFlyout), new PropertyMetadata(null));

    public DataTemplate ItemTemplate
    {
        get { return (DataTemplate)GetValue(ItemTemplateProperty); }
        set { SetValue(ItemTemplateProperty, value); }
    }

    public static readonly DependencyProperty ItemTemplateProperty =
        DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(ListViewFlyout), new PropertyMetadata(null));

    public object SelectedItem
    {
        get { return (object)GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }
    }

    public static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register("SelectedItem", typeof(object), typeof(ListViewFlyout), new PropertyMetadata(null));

    public ListViewFlyout()
    {
        // initialization
        this.Placement = FlyoutPlacementMode.Full;
        _listView = new ListView
        {
            Opacity = 0,
            IsItemClickEnabled = true
        };

        this.Opened += ListViewFlyout_Opened;
        this.Closed += ListViewFlyout_Closed;
    }

    private async void ListViewFlyout_Opened(object sender, object e)
    {
        await Task.Delay(400);

        if (!_listView.Items.Any())
        {
            // assign the listView as the Content of this 'custom control'
            _listView.ItemsSource = this.ItemsSource;
            _listView.ItemTemplate = this.ItemTemplate;
            _listView.GroupStyle.Add(new GroupStyle { HeaderTemplate = this.HeaderTemplate });
            this.Content = _listView;

            // whenever an item is clicked, we close the Layout and assign the SelectedItem
            _listView.ItemClick += ListView_ItemClick;
        }

        // animate in the list
        var animation = new DoubleAnimation
        {
            Duration = TimeSpan.FromMilliseconds(200),
            To = 1
        };
        Storyboard.SetTarget(animation, _listView);
        Storyboard.SetTargetProperty(animation, "Opacity");
        var storyboard = new Storyboard();
        storyboard.Children.Add(animation);
        storyboard.Begin();
    }

    private void ListViewFlyout_Closed(object sender, object e)
    {
        _listView.Opacity = 0;
    }

    private async void ListView_ItemClick(object sender, ItemClickEventArgs e)
    {
        this.SelectedItem = e.ClickedItem;
        this.Hide();

        // to be removed
        await Task.Delay(1000);
        var dialog = new MessageDialog(e.ClickedItem.ToString() + " was clicked 1 sec ago!");
        await dialog.ShowAsync();
    }
}
xaml变得如此简单

    <AppBarButton Icon="Caption">
        <AppBarButton.Flyout>
            <local:ListViewFlyout ItemsSource="{Binding Source={StaticResource ItemsViewSource}}" ItemTemplate="{StaticResource ListViewItemTemplate}" HeaderTemplate="{StaticResource GroupHeaderTemplate}" FlyoutPresenterStyle="{StaticResource FlyoutPresenterStyle}" />
        </AppBarButton.Flyout>
    </AppBarButton>

我也有同样的问题,我找到了解决办法。 我发现即使没有解决办法,性能也相当差。在我的设备(Lumia 920)上完全加载大约需要1s的时间

我认为责任在于
项目跟踪面板
,它是
列表视图
的默认
项目面板
。当我使用另一个面板时,问题不会发生。但是,当我关闭并重新打开弹出按钮时,scrollviewer偏移量不会重置,因此我必须手动执行此操作

因此,为了保持虚拟化,我使用了
VirtalizingStackPanel

<ListView.ItemsPanel>
    <ItemsPanelTemplate>
        <VirtualizingStackPanel />
    </ItemsPanelTemplate>
</ListView.ItemsPanel>
我订阅弹出按钮
打开
关闭
事件:

<Flyout Placement="Full"
        Opened="Flyout_Opened"
        Closed="Flyout_Closed" />
此外,默认情况下,弹出按钮有一个
ScrollViewer
,这将破坏虚拟化。
您需要将其从
FlyoutPresenter
控制模板中删除,或使用
ScrollViewer禁用它。VerticalScrollMode

结果是,奇怪的动画来自
项目跟踪面板
。因此,如果(且仅当)不需要虚拟化,可以将
StackPanel
指定为
ItemsPanel

<Flyout>
    <ListView ItemsSource="{Binding Source={StaticResource ItemsViewSource}}"
              Margin="20 0">
        <ListView.GroupStyle>
            <GroupStyle HeaderTemplate="{StaticResource GroupHeaderTemplate}" />
        </ListView.GroupStyle>
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel />
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
    </ListView>
</Flyout>


我知道如何更改项目的外观,以及如何显示具有分组功能的选择器。这里唯一的问题是标准的
ListPickerFlyout
不支持这一点。谢谢。我明白了。然而,当我第一次在emulator上打开弹出按钮时,动画错误仍然存在。我认为时间应该进一步调整。嘿@altso,你是在真实的设备上测试这个,还是在没有调试器的情况下运行模拟器?因为当附加调试器时,运行应用程序时会严重影响性能。我已经在520、920和1020上测试过了,都很好。你说你看了所有的动画,或者你就是找不到那件特定的东西的动画?@ChrisW。我找不到适用于该特定对象的模式。似乎设置
flyorpresenter
ScrollViewer.VerticalScrollMode
就足以启用虚拟化。谢谢你的提示。还有一件事需要注意的是,你也会丢失粘性标题。:)
private void ListView_Loaded(object sender, RoutedEventArgs e)
    {
        var listView = (ListView)sender;            
        var scrollviewer = listView.FindFirstChild<ScrollViewer>();
        scrollviewer.ScrollToVerticalOffset(0);
    }
<ListView Visibility="Collapsed" />
<Flyout Placement="Full"
        Opened="Flyout_Opened"
        Closed="Flyout_Closed" />
private async void Flyout_Opened(object sender, object e)
    {
        await Task.Delay(400);
        var listView = (ListView)((Flyout)sender).Content;
        listView.Visibility = Windows.UI.Xaml.Visibility.Visible;
    }

    private void Flyout_Closed(object sender, object e)
    {
        var listView = (ListView)((Flyout)sender).Content;
        listView.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
    }
<Flyout>
    <ListView ItemsSource="{Binding Source={StaticResource ItemsViewSource}}"
              Margin="20 0">
        <ListView.GroupStyle>
            <GroupStyle HeaderTemplate="{StaticResource GroupHeaderTemplate}" />
        </ListView.GroupStyle>
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel />
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
    </ListView>
</Flyout>