You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UWP ListView绑定ObservableCollection<KeyValuePair<int,RelativePanel>>时快速滚动显示错误项问题求助

Fixing UWP ListView Scrolling Glitch with Virtualization

Hey, let's break down why you're seeing those messed-up items when scrolling quickly and get this sorted properly. The root cause here is that you're embedding UI elements (RelativePanel) directly into your data collection—and ListView's virtualization system (which reuses item containers to save memory) doesn't play nice with that. UI elements can only belong to one parent container at a time, so when ListView reuses an old container for a new item, you end up with conflicting references that cause the display chaos you're seeing.

Step 1: Separate Data from UI (The Right Way)

First, let's create a proper data model for your products instead of using KeyValuePair with a UI control. This keeps your data clean and decoupled from how it's displayed:

// Define this in your project (make sure it's accessible to your XAML)
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    // Add any other properties you need later (Price, Description, etc.) here
}

Step 2: Update Your Data Fetching Logic

Modify your GetProducts method to return a list of Product objects instead of UI controls. This way you're working with raw data, not pre-built UI:

public static async Task<List<Product>> GetProducts()
{
    var productIDs = await SqlHandler.ReturnListQuery<int>($"SELECT id FROM {productTable}");
    var productNames = await SqlHandler.ReturnListQuery<string>($"SELECT name FROM {productTable}");
    
    var products = new List<Product>();
    for(int i = 0; i < productIDs.Count; i++)
    {
        products.Add(new Product
        {
            Id = productIDs[i],
            Name = productNames[i]
        });
    }
    return products;
}

Step 3: Rewrite the ListView XAML

Now we'll define the UI directly in the DataTemplate instead of binding to a pre-built RelativePanel. This lets ListView handle virtualization correctly, and you can still use SelectedValuePath to get the product ID easily:

<!-- Don't forget to add the namespace for your Product class at the top of your XAML file, e.g.:
xmlns:local="using:YourProjectNamespace"
-->
<ListView x:Name="lst_Products" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="16,124,16,16" Width="300" 
          ContainerContentChanging="lst_Products_ContainerContentChanging" Loaded="lst_Products_Loaded" 
          BorderBrush="Black" BorderThickness="2" CornerRadius="16"
          SelectedValuePath="Id"> <!-- This still lets you get the selected Product's ID via SelectedValue -->
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="local:Product">
            <RelativePanel>
                <TextBlock Text="{x:Bind Name}" />
                <!-- Add any additional controls here later (e.g., price labels, images) by binding to Product properties -->
            </RelativePanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Step 4: Update the Loaded Event

Now bind the ListView to your clean Product collection:

private async void lst_Products_Loaded(object sender, RoutedEventArgs e)
{
    var products = await ProductManager.GetProducts();
    lst_Products.ItemsSource = new ObservableCollection<Product>(products);
}

Why This Fixes the Scrolling Glitch

By separating your data (Product objects) from the UI (defined in the DataTemplate), ListView's virtualization can safely reuse item containers. Each time a container is reused, the DataTemplate will re-render the UI based on the new Product data—no more conflicting UI element parent references, no more messed-up items when scrolling fast.

Quick Note on Your ContainerContentChanging Event

Your current code for setting alternate row backgrounds works fine here, but just a heads-up: since ListView reuses containers, this event will fire both for new containers and recycled ones. Your current logic already overwrites the background every time, so you don't need to adjust it—this will keep the alternating rows working correctly even with virtualization.

This approach also makes it way easier to add more product info later: just add a property to the Product class, then add a new control in the DataTemplate bound to that property. No more building UI elements in code-behind!

内容的提问来源于stack exchange,提问作者chsimons

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 16:42:45