【问题标题】:Windows 10 UWP - GridView Items With no DataContext when Not VisibleWindows 10 UWP - 不可见时没有 DataContext 的 GridView 项目
【发布时间】: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 事件)。

有没有人知道如何在控件可见时获得通知?这似乎是一个通知错误,或者我缺少一些绑定的东西。

谢谢!

【问题讨论】:

    标签: c# windows gridview win-universal-app


    【解决方案1】:

    有没有人知道如何在控件可见时获得通知?

    当您的RsrItemGridViewItem 变为可见时,您不能在此处使用FrameworkElement.Loaded event 来获得通知,此事件在FrameworkElement 已构建并添加到对象树并准备好进行交互时发生。

    GirdView 控件实现UI virtualization 以获得更好的UI 性能,如果您的GridView 绑定到许多项目的集合,它可能只下载项目1-50,当用户滚动到列表末尾附近时,然后下载项目 51 – 100,依此类推。但是例如,现在只显示了 20 个项目,但它可能已经加载了 45 个项目,此时无法看到 25 个项目。

    如果您将GridView 的默认ItemsPanel (即ItemsWrapGrid)更改为例如VariableSizedWrapGridGridView 将失去虚拟化,所有项目将同时加载,即使大多数项目无法加载在一瞬间被看到。

    对于您的问题,我认为您可以尝试使用您的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} 添加到我想要收到更新通知的图像中。 &lt;Image DataContext="{Binding}" DataContextChanged="ItemImage_DataContextChanged" /&gt; 主控件不会收到 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 更改的通知,但会通知子元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多