Windows 10 UWP - 不可见时没有DataContext的GridView项

时间:2016-04-23 00:42:46

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

我在UWP应用程序中遇到了一个问题,我正在研究......

GridView中的项目正确加载,但是不在视图范围内(在页面外且不可见)的项目没有分配DataContext,并且在分配DataContext时不会触发任何事件。各种绑定确实有效,因为绑定的TextBlock会更新,但正常的事件工作流和Loaded事件都会变得奇怪。

Null DataContext in Loaded Event

<GridView Grid.Row="1" Name="SearchGrid" ItemsSource="{Binding SearchItems}" ItemClick="SearchGrid_ItemClick">
        <GridView.ItemTemplate>
            <DataTemplate>
                <local:RsrItemGridViewItem />
            </DataTemplate>
        </GridView.ItemTemplate>
    </GridView>

网格都正确显示,除了能够正确延迟加载某些项目,因为DataContext在加载时没有设置(并且在更新上下文时不会触发DataContextChanged事件)

当控件变得可见时,有没有人知道如何获得通知?这似乎是一个通知错误,或者有一些我错过的具有约束力的东西。

谢谢!

2 个答案:

答案 0 :(得分:0)

  

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

RsrItemGridViewItem变得可见时,您无法在此处使用FrameworkElement.Loaded event获取通知,此事件在构建FrameworkElement并添加到对象树时发生,并且已准备好进行交互

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

如果您更改ItemsPanel GridView的默认ItemsWrapGrid,例如VariableSizedWrapGrid,则GridView将失去虚拟化,并且所有项目都将被加载与此同时,甚至大多数人都无法在一瞬间看到。

对于你的问题,我认为你可以尝试的是计算ScrollViewer的VerticalOffset与你的GridView的身高以及项目的数量显示,然后您就可以知道此时显示的是哪些项目。

例如:

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控件的布局适应应用程序的大小,当前显示的计数是动态的,您可以尝试其他基于高度的属性(例如每个项目的高度) )和ScrollViewer的VerticalOffset来计算,没有现成的方法来完成你的工作,计算起来有点复杂,但我认为目前还没有更好的解决方案。

答案 1 :(得分:-1)

用这个做了一些测试之后,我发现的工作(虽然它不是很干净,我相信有一个绑定错误)是将自定义控件添加到GridView,然后在网格视图中添加一个{ {1}}我希望收到有关更新的通知。

DataContext={Binding}

主控件不会收到DataContext更改的通知,但会通知子元素。