ListView.ContainerFromItem returns null after a new item is added in windows 8.1 store XAML

前端 未结 1 968
长情又很酷
长情又很酷 2021-01-14 19:02

I have a simple ListView with no item template and the SelectionChanged event setup:

    

        
相关标签:
1条回答
  • 2021-01-14 19:32

    I can tell you.

    What you are experiencing here is a problem of timing. How fast do you think you can add an item to a collection? Fast - just a millisecond or two. How fast do you think it takes the ListView to set the SelectedItem property and raise the SelectionChanged event? Fast - a millisecond or two. But, how fast do you think it takes the ListView to actually render the new item on the screen and generate the container for it? A long time - like 10 to 100 milliseconds, depending on the complexity of the DataTemplate.

    I realize your test didn't set the ItemTemplate, and I assume you did it that way assuming that it would render faster - maybe instant. But there is a default DataTemplate in every ItemsControl. And, even a simple DataTemplate like the built-in one, still takes more time than it takes you to advance a single C# line.

    This code will illustrate what I mean:

    async void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        var items = Enumerable.Range(1, 10)
            .Select(x => new Item { FirstName = "Bob", LastName = "Smith" + x.ToString() });
        var list = new ObservableCollection<Item>(items);
        MyListView.ItemsSource = list;
        var item = new Item { FirstName = "Jerry", LastName = "Nixon" };
        list.Add(item);
        await Task.Delay(1000);
        MyListView.SelectedItem = item;
    }
    
    private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        System.Diagnostics.Debug.Assert(e.AddedItems.Any());
        var listview = sender as ListView;
        var container = listview.ContainerFromItem(e.AddedItems.First());
        System.Diagnostics.Debug.Assert(container != null);
        var presenter = VisualTreeHelper.GetChild(container, 0);
        System.Diagnostics.Debug.Assert(presenter != null);
    }
    

    Please notice the Delay code; this is what makes it work.

    Hopefully, you simplified your question and that is why you are doing the work in code-behind and not in a view model. Fine. First, be sure and handle this type of logic in Loaded so you can be confident that your ListView is even available. Then again, do this in your view model.

    So, I have answered your question. Why? Because of timing.

    Seems to me it might all be solved with a simple view model, but then again, I only know a little bit of your situation here. Maybe there's something I am not seeing.

    Best of luck!

    0 讨论(0)
提交回复
热议问题