WPF中绑定视图到ViewModel时的ToolTip内存泄漏问题

3

我有一个基于WPFMVVM的应用程序。它在ListBox中显示了一组Images,每张图片都与不同的会话相关联。

我的ListBox ItemTemplate看起来像这样:

<ListBox.ItemTemplate>
   <DataTemplate>
      <Image 
          Source="{Binding IsClaims,Converter={StaticResource PolicyClaimsImageSelector}}" 
          ToolTipService.ShowDuration="7000">
             <Image.ToolTip>                                           
                <StackPanel>
                  <TextBlock Text="{Binding WorkingSessionName}" />
                  <Views:ToolTipView DataContext="{Binding ThisViewModel}"/>
                </StackPanel>
            </Image.ToolTip>
      </Image>
   </DataTemplate>
</ListBox.ItemTemplate>

我的视图模型

public class Session : BindableBase
{
    private MainViewModel _ThisViewModel;
    public MainViewModel ThisViewModel
    {
        get
        {
            return _ThisViewModel;
        }
        set
        {
            _ThisViewModel = value;
            NotifyPropertyChanged();
        }
    }
}

每次工具提示出现时都会发生内存泄漏,不知道为什么会这样。我的问题是,是否有必要在显示工具提示后使用 ToolTipdispose 任何内存?如果需要,该如何操作?
编辑
没有订阅任何事件。只绑定了不同视图模型的 DataContext

ToolTipView.XAML

 <DockPanel>
    <xcad:DockingManager  DockPanel.Dock="Left" Grid.Row="2" BorderBrush="Black" BorderThickness="1">
        <xcad:DockingManager.Theme>
            <xcad:MetroTheme />
        </xcad:DockingManager.Theme>
        <xcad:LayoutRoot >
            <xcad:LayoutPanel Orientation="Horizontal" >
                <xcad:LayoutAnchorablePaneGroup Orientation="Horizontal" DockMinWidth="150" >
                    <xcad:LayoutAnchorablePane >
                        <xcad:LayoutAnchorable Title="Folder" x:Name="ExplorerView" AutoHideWidth="300">
                            <Views:ExplorerView DataContext="{Binding ExplorerViewModel}"/>
                        </xcad:LayoutAnchorable>
                    </xcad:LayoutAnchorablePane>
                </xcad:LayoutAnchorablePaneGroup>
                <xcad:LayoutAnchorablePaneGroup Orientation="Horizontal" DockMinWidth="450" >
                    <xcad:LayoutAnchorablePane >
                        <xcad:LayoutAnchorable Title="Documents"  x:Name="TOC">
                            <Views:TableOfContentView  DataContext="{Binding TableOfContentViewModel}"/>
                        </xcad:LayoutAnchorable>
                    </xcad:LayoutAnchorablePane>
                </xcad:LayoutAnchorablePaneGroup>
                <xcad:LayoutAnchorablePaneGroup Orientation="Vertical" DockMinWidth="320">
                    <xcad:LayoutAnchorablePane DockMinHeight="400" >
                        <xcad:LayoutAnchorable Title="Properties"  x:Name="Property">
                            <Views:PropertyView DataContext="{Binding PropertyViewModel}"/>
                        </xcad:LayoutAnchorable>
                    </xcad:LayoutAnchorablePane>
                    <xcad:LayoutAnchorablePane >
                        <xcad:LayoutAnchorable Title="Search"  x:Name="Search">
                            <Views:SearchPanel DataContext="{Binding SearchViewModel}"/>
                        </xcad:LayoutAnchorable>
                    </xcad:LayoutAnchorablePane>
                </xcad:LayoutAnchorablePaneGroup>                    
            </xcad:LayoutPanel>
        </xcad:LayoutRoot>
    </xcad:DockingManager>
</DockPanel>

编辑

我尝试将ToolTipView.XAML中的所有Views移除,如下所示,在ToolTip中显示没有任何视图的工具提示会导致相同的内存泄漏

现在我的ToolTipView.XAML看起来像这样:

<UserControl x:Class="ecclient.viewer.Views.ToolTipView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:Views="clr-namespace:ecclient.viewer.Views">
</UserControl>

我正在使用VS2015调试应用程序,它内置了一个名为“诊断工具”的工具,当我将鼠标悬停在每个图像上时,它会显示内存升高情况,就像ToolTip一样。 - Abin
你在 ToolTipView 里面做了什么?如果你订阅了 ThisViewModel 的任何事件,那么你会泄漏的。请发布 ToolTipView 的代码。 - atomaras
@atomaras 在问题中添加了视图的代码。没有订阅任何事件,ViewModels 中只有属性和命令。 - Abin
@AbinMathew 我看到有多个视图被创建并绑定到ViewModels。由于您的ViewModels通过MainVM静态引用,因此如果任何一个视图在没有使用WeakEventListener或取消订阅的情况下在ViewModel上附加了任何类型的EventHandler,则会导致内存泄漏。 - atomaras
@AbinMathew CommandBindings确实会连接CanExecuteChanged事件...这可能会导致泄漏。 - atomaras
显示剩余4条评论
2个回答

0

我通过创建一个接口来模拟实际的绑定,已经解决了这个问题。请参见下面的代码。

 public IExplorer ToolTipExplorerViewModel
    {
        get { return ExplorerViewModel; }            
    }

    public ITableOfContents ToolTipTableOFContents
    {
        get { return TableOfContentViewModel; }
    }

现在我将这些属性与 ToolTipView 绑定:

<Views:ExplorerView DataContext="{Binding ToolTipExplorerViewModel}" Grid.Column="0"/>
<Views:TableOfContentView  DataContext="{Binding ToolTipTableOFContents}" Grid.Column="1" />      

现在随着我们更改工具提示,内存不再增长。


0
这可能有点冒险,但可以尝试一下。我曾经遇到过某些图形驱动程序会在 WPF 中触发泄漏的问题。我们最终禁用了 WPF 的硬件加速并重新测试。虽然不是理想的答案,但足以让我们解决客户长时间运行客户端时的问题。
在注册表中(系统范围内)
[HKEY_CURRENT_USER\Software\Microsoft\Avalon.Graphics]
"DisableHWAcceleration"=dword:00000001

或者通过应用程序本身的代码:

   RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;

您可以使用“WPF性能套件”并启用软件渲染元素的紫色色调来测试通过软件或硬件呈现的内容。
希望这可以帮到您。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接