Windows 10 UWP - 不可见时没有 DataContext 的 GridView 项目
Posted
技术标签:
【中文标题】Windows 10 UWP - 不可见时没有 DataContext 的 GridView 项目【英文标题】:Windows 10 UWP - GridView Items With no DataContext when Not Visible 【发布时间】:2016-08-16 18:17:23 【问题描述】:我正在处理的 UWP 应用程序中的 GridView 存在问题...
GridView 中的项目可以正确加载,但是不在视图中的项目(离开页面且不可见)没有分配 DataContext,并且在分配 DataContext 时不会触发任何事件。各种绑定确实可以作为绑定的 TextBlock 进行更新,但正常的事件工作流程和 Loaded 事件变得很奇怪。
<GridView Grid.Row="1" Name="SearchGrid" ItemsSource="Binding SearchItems" ItemClick="SearchGrid_ItemClick">
<GridView.ItemTemplate>
<DataTemplate>
<local:RsrItemGridViewItem />
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
网格都正确显示,除了能够正确延迟加载某些项目,因为在加载时未设置 DataContext(并且更新上下文时未触发 DataContextChanged 事件)。
有没有人知道如何在控件可见时获得通知?这似乎是一个通知错误,或者我缺少一些绑定的东西。
谢谢!
【问题讨论】:
【参考方案1】:有没有人知道如何在控件可见时获得通知?
当您的RsrItemGridViewItem
变为可见时,您不能在此处使用FrameworkElement.Loaded event 来获得通知,此事件在FrameworkElement 已构建并添加到对象树并准备好进行交互时发生。
GirdView
控件实现UI virtualization 以获得更好的UI 性能,如果您的GridView
绑定到许多项目的集合,它可能只下载项目1-50,当用户滚动到列表末尾附近时,然后下载项目 51 – 100,依此类推。但是例如,现在只显示了 20 个项目,但它可能已经加载了 45 个项目,此时无法看到 25 个项目。
如果您将GridView
的默认ItemsPanel
(即ItemsWrapGrid
)更改为例如VariableSizedWrapGrid
,GridView
将失去虚拟化,所有项目将同时加载,即使大多数项目无法加载在一瞬间被看到。
对于您的问题,我认为您可以尝试使用您的GridView
的高度计算ScrollViewer
的VerticalOffset 并显示项目的计数,然后您可以知道哪些项目显示在这一刻。
例如这里:
private ObservableCollection<MyList> list = new ObservableCollection<MyList>();
public MainPage()
this.InitializeComponent();
this.Loaded += MainPage_Loaded;
private double viewheight;
private void MainPage_Loaded(object sender, RoutedEventArgs e)
var scrollViewer = FindChildOfType<ScrollViewer>(gridView);
scrollViewer.ViewChanged += ScrollViewer_ViewChanged;
viewheight = gridView.ActualHeight;
private void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
var scrollViewer = sender as ScrollViewer;
var Y = scrollViewer.VerticalOffset;
//calculate here to get the displayed items.
public static T FindChildOfType<T>(DependencyObject root) where T : class
var queue = new Queue<DependencyObject>();
queue.Enqueue(root);
while (queue.Count > 0)
DependencyObject current = queue.Dequeue();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(current); i++)
var child = VisualTreeHelper.GetChild(current, i);
var typedChild = child as T;
if (typedChild != null)
return typedChild;
queue.Enqueue(child);
return null;
protected override void OnNavigatedTo(NavigationEventArgs e)
list.Clear();
for (int i = 0; i < 200; i++)
list.Add(new MyList text = "Item " + i );
由于GridView
控件的布局是自适应app的大小,当前显示的计数是动态的,你可以尝试其他基于高度的属性(例如每个项目的高度)和ScrollViewer
的VerticalOffset来计算,有没有现成的方法来完成你的工作,计算起来有点复杂,但我认为目前没有更好的解决方案。
【讨论】:
在对此进行了一些测试后,我发现有效(虽然它不是很干净,而且我相信绑定存在错误)是将自定义控件添加到 GridView,然后在网格视图将DataContext=Binding
添加到我想要收到更新通知的图像中。 <Image DataContext="Binding" DataContextChanged="ItemImage_DataContextChanged" />
主控件不会收到 DataContext 更改的通知,但会通知子元素。
@Josh,问题是,即使它有一个DataContext,并不意味着那个项目在那一刻可以被看到。
是的......但我认为真正的问题是,当孩子们收到 DataContextChanged 通知时,绑定到同一上下文的父母没有收到这些通知。在我上面的示例中,RsrItemGridViewItem 的子项收到 DataContextChanged 通知,但主 RsrItemGridViewItem 没有收到通知。
@Josh,DataContextChanged 具有路由行为,但不是真正的路由事件(它没有 RoutedEvent 标识符)。此外,它从父级路由到子级,而真正的路由事件从子级路由到父级。可以参考FrameworkElement.DataContextChanged event。这不是一个错误,它只是被设计成这样。【参考方案2】:
在对此进行一些测试之后,我发现有效(虽然它不是很干净,而且我相信绑定存在错误)是将自定义控件添加到 GridView,然后在网格视图中添加一个 @ 987654321@ 发送到我想收到更新通知的图片。
<UserControl ...><Image DataContext="Binding" DataContextChanged="ItemImage_DataContextChanged" /></UserControl>
主控件不会收到 DataContext 更改的通知,但会通知子元素。
【讨论】:
以上是关于Windows 10 UWP - 不可见时没有 DataContext 的 GridView 项目的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 C# 从 Windows 10 日历中检索 UWP 中的约会
UWP StoreProductQueryResult不返回任何产品
在Windows 10 C#UWP通用Windows应用程序中获取UserName