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>