0

I have a ListView in a WinUI 3 app (target framework net6.0-windows10.0.19041.0) with a data template that contains a TextBox. The ItemsSource is bound to an ObservableCollection in the code-behind file. There is also a button after the list to clear the collection and add a new item.

I noticed a strange behaviour: if i write anything in the TextBox, that text is retained after i click the Clear button. I would expect it to insert a completely new TextBox in the ListView, with no text in it.

Why does this happen? Does it have something to do with virtualization?

Here is the xaml file:

<Window
    x:Class="WinUISample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WinUISample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <ListView ItemsSource="{x:Bind _items }" >
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="x:String">
                    <TextBox Width="250" /> <!-- intentionally empty -->
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

        <Button Click="myButton_Click">Clear</Button>
    </StackPanel>
</Window>

And this is the code-behind file:

using Microsoft.UI.Xaml;
using System.Collections.ObjectModel;

namespace WinUISample
{
    public sealed partial class MainWindow : Window
    {
        private readonly ObservableCollection<string> _items;

        public MainWindow()
        {
            InitializeComponent();

            _items = new ObservableCollection<string>(new[]
            {
                "1"
            });
        }

        private void myButton_Click(object sender, RoutedEventArgs e)
        {
            _items.Clear();
            _items.Add("1");
        }
    }
}

1 Answer 1

1

This should be because of its Virtualization feature. Since you are not binding your Text, you'll get the same text.

You can avoid this behavior by binding your Text,

<TextBox Width="250" Text="{x:Bind}" />

or by changing the ItemsPanel.

<ListView ItemsSource="{x:Bind _items}" >
    <!--<ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>-->
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="x:String">
            <TextBox Width="250" />
            <!-- intentionally empty -->
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
Sign up to request clarification or add additional context in comments.

2 Comments

Would you be able to explain please why changing the ItemsPanel does the trick here? I don't understand why the default "recycles" the control in an unwanted manner, to me it looks like a bug.
As it's in the link I posted, this virtualization feature tries to reuse instances (in this case TextBox) to make the ListView performant. The default ItemsPanel (VirtualizingStackPanel) enables virtualizing. So overriding the ItemsPanel to a usual StackPanel disables this virtualizing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.