c# - WPF 组合框 "leaks"内存

标签 c# wpf memory-leaks combobox

我遇到了 WPF 中组合框的问题,它们似乎卡在打开它们的第一个 DataContext 上。当我更改 ComboBox 上的 DataContext 时,子 PopupRoot 对象仍然引用旧的 DataContext。

起初我以为我们做错了什么,但我无法弄清楚那可能是什么,所以我试图简化。我设法以一种非常简单的形式重新创建了我在应用程序中看到的行为,因此它看起来更像是 WPF ComboBox 实现中的错误。这听起来有点争议,所以我想我应该转向 stackoverflow 寻求帮助。

示例的核心代码如下:

<Window x:Class="ComboBoxTest.MainWindow" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="150" Width="525">
    <DockPanel>
        <Button Click="ReloadModel" Width="137" Height="40">Reload Model</Button>
        <ComboBox Name="ComboBox" 
            ItemsSource="{Binding AvailableOptions}" 
            SelectedItem="{Binding SelectedOption}" 
            Width="235" Height="43">
        </ComboBox>
    </DockPanel>
</Window>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var newModel = new ViewModel();
        ComboBox.DataContext = newModel;
    }

    private void ReloadModel(object sender, RoutedEventArgs e)
    {        
        var newModel = new ViewModel();
        ComboBox.DataContext = newModel;
    }
}

public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
        : this(new[] { "Option 1", "Option 2", "Option 3" })
    { }

    public ViewModel(IEnumerable<string> options)
    {
        _selectedOption = options.First();
        _availableOptions = new ObservableCollection<string>(options);
    }

    protected void RaisePropertyChanged(string propertyName)
    {
        var propertyChangedHandler = PropertyChanged;
        if (propertyChangedHandler != null)
        {
            propertyChangedHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;

    private readonly ObservableCollection<string> _availableOptions;
    public ObservableCollection<string> AvailableOptions
    {
        get
        {
            return _availableOptions;
        }
    }

    private string _selectedOption;
    public string SelectedOption
    {
        get { return _selectedOption; }
        set
        {
            if (_selectedOption == value)
            {
                return;
            }
            _selectedOption = value;
            RaisePropertyChanged("SelectedOption");
        }
    }
}

重现步骤:
1) 运行应用程序
2) 打开组合框(以便呈现下拉选项)
3)点击“重新加载模型”按钮

此时将有两个 ViewModel 对象,较旧的、意外的实例是根状的,如下所示: ViewModel->PopupRoot->Popup->ComboBox->MainWindow->App

这是一个错误还是我做错了?

埃蒙

最佳答案

Joe 的评论让我的注意力重新回到这个老问题上,我已经解决了这个问题供自己使用。最后,我编写了一个可以附加到处理内存泄漏的组合框的行为。

我在这里发布了代码:https://github.com/EamonHetherton/Demos/blob/master/StackOverflow/18096050/StopComboBoxMemoryLeakBehaviour.cs

买者自负:此解决方案依赖于反射(reflection)和可能带来的脆弱性。它对我有用,YMMV。

关于c# - WPF 组合框 "leaks"内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18096050/

相关文章:

c# - 在 Winforms 中编写代码的最佳和合适方法是什么?

c# - Enum.GetValues() 不会返回您(我)期望的内容

c# - 我如何转换 HH :MM:SS into just seconds using C#.net?

c# - Control.Dispatcher.BeginInvoke() 和 Control.Dispatcher.Invoke() 顺序执行是不是很困惑?

java - Apache ActiveMQ 中的内存泄漏

c# - 写入套接字 : Unable to write data to transport connection 时出现异常

c# - 为什么 Browsable(false) 不隐藏 DataGrid 中的列

.net - View 或 View 模型哪个先出现?

c++ - For 循环中的指针

java - HSQL系统内存使用量增加