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

WinUI中ListView重置后TextBox文本残留问题咨询

问题:WinUI 3 ListView中TextBox内容未随集合更新清空

我在目标框架为net6.0-windows10.0.19041.0的WinUI 3应用中,使用了包含TextBox的ListView,其ItemsSource绑定至后台代码中的ObservableCollection。列表后方设有按钮,用于清空集合并添加新项。

异常现象:在TextBox中输入内容后,点击清除按钮,文本仍会保留。预期应为ListView生成全新的空白TextBox。

请问该现象的原因是什么?是否与Virtualization(虚拟化)有关?

相关代码

XAML文件

<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>

后台代码文件

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");
        }
    }
}

原因分析

这个现象确实和ListView的虚拟化机制直接相关。

WinUI 3的ListView默认开启虚拟化(默认使用VirtualizingStackPanel作为ItemsPanel),核心逻辑是复用UI元素以提升性能:当集合项被移除后,对应的ListItem容器不会立即销毁,而是被放入回收池;后续添加新项时,系统会直接复用这些已有的容器,而非创建全新的控件。

你的代码里,TextBox没有和集合项(string类型)做任何绑定,只是一个独立的输入控件。清空集合再添加新项时,ListView复用了之前的ListItem容器,里面的TextBox自然会保留之前输入的内容——毕竟没有绑定关系来同步新项的值(就算新项是"1",TextBox也没和这个值关联)。

顺带提一句:如果关闭虚拟化,这个问题就不会出现,因为此时ListView会为每个项创建全新的容器,更新集合时会生成新的空白TextBox。但虚拟化是默认行为,所以才会触发这个复用问题。

解决方法

有两种常用的修复方式:

方式一:给TextBox添加数据绑定

让TextBox的Text属性和集合项绑定,这样集合更新时,Text会同步为新项的值。修改DataTemplate:

<DataTemplate x:DataType="x:String">
    <TextBox Width="250" Text="{x:Bind Mode=OneWay}" />
</DataTemplate>

如果需要点击按钮后TextBox是空白的,把添加的项改成空字符串即可:

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

方式二:禁用ListView虚拟化

如果你的列表项数量很少,不需要虚拟化的性能优化,可以直接禁用:

<ListView ItemsSource="{x:Bind _items}" ScrollViewer.IsVirtualizing="False">
    <!-- 原有ItemTemplate不变 -->
</ListView>

这样每次更新集合时,ListView都会创建全新的容器,TextBox自然是空白的。


内容的提问来源于stack exchange,提问作者Gabriel S.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 18:18:50