gpt4 book ai didi

xaml - Flyout 转换问题中的 ListView

转载 作者:行者123 更新时间:2023-12-01 12:40:35 30 4
gpt4 key购买 nike

我在 Flyout 中使用分组的 ListView,当弹出窗口打开时,组标题出现奇怪的 UI 问题。它发生的时间只有几分之一秒,但大多数用户仍会注意到。

header animation bug

XAML(摘自完整的重现样本 http://ge.tt/1DWlXbq1/v/0?c):

<Page.Resources>
<DataTemplate x:Key="GroupHeaderTemplate">
<ContentControl Content="{Binding Key}"
FontWeight="Bold"
FontSize="{ThemeResource TextStyleLargeFontSize}"
Foreground="{ThemeResource PhoneAccentBrush}"
Margin="0 20" />
</DataTemplate>
<CollectionViewSource x:Key="ItemsViewSource"
IsSourceGrouped="True"
Source="{Binding Items}" />
</Page.Resources>

<Page.BottomAppBar>
<CommandBar>
<AppBarButton Icon="Caption">
<AppBarButton.Flyout>
<Flyout>
<ListView ItemsSource="{Binding Source={StaticResource ItemsViewSource}}"
Margin="20 0">
<ListView.GroupStyle>
<GroupStyle HeaderTemplate="{StaticResource GroupHeaderTemplate}" />
</ListView.GroupStyle>
</ListView>
</Flyout>
</AppBarButton.Flyout>
</AppBarButton>
</CommandBar>
</Page.BottomAppBar>

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

我试图在 ListView/Flyout 的默认样式中找到相应的 Storyboard或过渡,但无法找到。

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

最佳答案

消除奇怪的动画错误的一种方法是让 Flyout控件的动画先运行,然后在动画结束后,显示ListView。 .

为此,您需要在 Flyout 中订阅以下事件控制。您还需要提供 ListView一个名字并设置它的Opacity0开始。

   <Flyout Opened="Flyout_Opened" Closed="Flyout_Closed">
<ListView x:Name="MyListView" Opacity="0" ItemsSource="{Binding Source={StaticResource ItemsViewSource}}" Margin="20 0">

然后在后面的代码中,显示 ListView短暂的延迟后。我创造了一点 Opacity ListView 的动画只是为了让整个过渡运行得更顺利。每次Flyout关闭,我们重置 ListView回到隐形状态。

private async void Flyout_Opened(object sender, object e)
{
// a short delay to allow the Flyout in animation to take place
await Task.Delay(400);

// animate in the ListView
var animation = new DoubleAnimation
{
Duration = TimeSpan.FromMilliseconds(200),
To = 1
};
Storyboard.SetTarget(animation, this.MyListView);
Storyboard.SetTargetProperty(animation, "Opacity");

var storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin();
}

private void Flyout_Closed(object sender, object e)
{
this.MyListView.Opacity = 0;
}

但是,提供了一个可能的解决方案后,我不认为使用 Flyout控制改变视觉风格是这里的正确方法。

Flyout控件不是为处理大量数据而设计的。它不支持虚拟化(我认为)。例如,如果您将项目数从 30 增加到 300,则在您按下按钮后加载将需要几秒钟。

更新(包括工作样本)

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

不幸的是ListPickerFlyout是密封的,所以我选择创建一个继承自 Flyout 的控件.

这很简单。基本上,该控件会公开类似 ItemsSource 的属性, SelectedItem等。它还订阅了 ItemClickListView 事件所以只要点击一个项目,它就会关闭 Flyout并填充 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>

注释在FlyoutPresenterStyle样式我创建了一个 Title也用于弹出窗口。

我还提供了一个功能齐全的示例 here .

关于xaml - Flyout 转换问题中的 ListView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25183938/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com