【问题标题】:Remove old generated ListView-Entries删除旧生成的 ListView-Entries
【发布时间】:2013-01-24 15:17:08
【问题描述】:

我在 XAML 中有一个 ListView-Control:

<ListView x:Name="conversationContent" Grid.Column="2" Margin="20,0,0,20" FontFamily="Global User Interface" >
    <ListView.Resources>
        <CollectionViewSource x:Name="conversationContentSource" IsSourceGrouped="False" />
        <DataTemplate x:Key="DataTemplate1">
            <Grid HorizontalAlignment="Stretch">
                <Border x:Name="messageBorder" BorderBrush="Black" BorderThickness="1" Margin="0" CornerRadius="2" VerticalAlignment="Center" HorizontalAlignment="{Binding MTY, Converter={StaticResource messageAlignment}}" Child="{Binding MSG, Converter={StaticResource messageToRTF}}" />
            </Grid>
        </DataTemplate>
    </ListView.Resources>
    <ListView.ItemsSource>
        <Binding Mode="OneWay" Source="{StaticResource conversationContentSource}"/>
    </ListView.ItemsSource>
</ListView>

CollectionViewSource 在运行时从后面的代码设置为某个 ObservableCollection&lt;Message&gt;

ObservableCollection 中的每个项目都由转换器解析,它将完整的消息(包括 BB 代码)转换为单个 RichTextBlock 元素,其中包含其他 UI 元素。

有时,CollectionViewSource.Source-Property 更改为另一个 ObersableCollection&lt;Message&gt;。发生这种情况时,ListView-Control 会构建新的 ItemList 并显示它。尽可能好。

问题是,旧的项目不会从内存中删除。手动运行 GC 不会在这里改变任何东西。

我尝试在更改源之前遍历旧项目并删除它们。

for (int ix = conversationContent.Items.Count - 1; ix >= 0; ix--) {
    Debug.WriteLine("Type: " + conversationContent.Items.ElementAt(ix));
    if (conversationContent.Items.ElementAt(ix) is RichTextBlock) {
        conversationContent.Items.RemoveAt(ix);
    }
}

但没有 RichTextBlock-Controls,只有“消息”类型的对象。为什么?

我需要说,一些生成的元素可以包含带有update-function 的 Canvas-Elements,该函数每 200 毫秒被计时器事件调用一次。这个事件绑定可以防止GC杀死这个对象吗?

当控件不再使用时,我需要一种方法来释放内存。

【问题讨论】:

    标签: c# xaml windows-runtime winrt-xaml windows-store-apps


    【解决方案1】:

    您可以并且应该使用RichTextBlock 作为您的ItemTemplate。研究附加的行为或附加的依赖属性,以了解如何将属性添加到 RichTextBlock,它将您的 BB 代码格式的消息转换为 RichTextBlock 内容。您可以在 WinRT XAML 工具包here 中查看将超链接文本添加到RichTextBlock 的示例。

    要调查内存泄漏,请检查以下问题:How to debug memory leaks in Windows Store apps?

    我看到的最常见的内存泄漏原因是从未删除的事件处理程序 - 确保删除您的 RichTextBlockUnloaded 事件上的所有处理程序。还要检查是否禁用了所有动画(例如在动画表情中)。

    【讨论】:

    • 非常感谢!笑脸的更新侦听器阻止 GC 杀死它们。 - 我要深呼吸一下你提到的依赖属性。
    【解决方案2】:

    首先你应该尝试使用 UI 虚拟化 -> http://blogs.southworks.net/dschenkelman/2009/01/29/how-to-show-large-amounts-of-data-in-wpf-using-ui-virtualization/

    这样,ListView 将回收用于呈现数据的控件,并且不会使用那么多内存。

    【讨论】:

    • MSDN 说:WPF 提供了ObservableCollection&lt;T&gt; 类,它是公开INotifyCollectionChanged 接口的数据集合的内置实现。 - 我是客人,你是说这个吗?
    • Nope :) 我的意思是,为了防止将所有这些对象加载到内存中,您可以同时使用 UI 和数据虚拟化。在 UI 虚拟化的情况下,用于呈现绑定到它的数据的控件将被回收,因此内存使用量更少。
    • 哇,行为改变了——方向错误。我正在显示聊天记录。很多文本行,一条包含 2000 个动画笑脸的消息。当我向下滚动时,应用程序会再次转换消息 - 并创建新元素。旧的不再可见,但它们仍在记忆中。编辑:我不希望条目在超出可见范围时被删除,我希望它们在更改 ItemSource 时被销毁。
    • 那么基本上只要代码中不存在对该项目集合的引用就足够了。使列表为空,以便释放它并由 GC 处理。
    • Collection 已清除并设置为 null - 生成的 RichTextBlock-Elements 仍然存在...有没有办法找到所有现有的 RichTextBlock-Elements?
    猜你喜欢
    • 1970-01-01
    • 2018-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    相关资源
    最近更新 更多