Wpf 如何正确实现XAML INotifyPropertyChanged以防止GDI泄漏
我们有一个应用程序,它使用WPF生成一个显示工作流的图像,这是一个非常古老的应用程序,直到最近我们开始遇到GDI泄漏时,它似乎工作得很好。我不熟悉WPF或GDI泄漏,但经过一些搜索,可能与WPF绑定有关。这些文章提到了将INotifyPropertyChanged接口实现到所有绑定到XAML上的类。我也这么做了,但问题仍然存在 我试图实现INotifyPropertyChanged,以解决内存分析器提到的问题类。还尝试将用户控件的DataContext属性设置为null 下面您可以看到在两个内存快照之间创建的新对象的支配者 下面您可以看到支配者背后的xaml和代码Wpf 如何正确实现XAML INotifyPropertyChanged以防止GDI泄漏,wpf,binding,gdi,inotifypropertychanged,Wpf,Binding,Gdi,Inotifypropertychanged,我们有一个应用程序,它使用WPF生成一个显示工作流的图像,这是一个非常古老的应用程序,直到最近我们开始遇到GDI泄漏时,它似乎工作得很好。我不熟悉WPF或GDI泄漏,但经过一些搜索,可能与WPF绑定有关。这些文章提到了将INotifyPropertyChanged接口实现到所有绑定到XAML上的类。我也这么做了,但问题仍然存在 我试图实现INotifyPropertyChanged,以解决内存分析器提到的问题类。还尝试将用户控件的DataContext属性设置为null 下面您可以看到在两个内存
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Priox.Core.Graph.UserControls
{
public partial class IndicatorClock : UserControl
{
public enum ClockTypes
{
None,
FixSla,
ResponseSla,
FixOla,
ResponseOla
};
public static readonly DependencyProperty ClockTypeProperty =
DependencyProperty.Register("ClockType", typeof(ClockTypes),
typeof(IndicatorClock), new FrameworkPropertyMetadata(ClockTypes.None));
public ClockTypes ClockType
{
get { return (ClockTypes)GetValue(ClockTypeProperty); }
set { SetValue(ClockTypeProperty, value); }
}
internal bool IsClockVisible { get; set; }
public Visibility ClockVisibility
{
get
{
if (IsClockVisible)
return System.Windows.Visibility.Visible;
return System.Windows.Visibility.Collapsed;
}
}
public double ClockBorderThickness
{
get
{
return 1.5;
}
}
public double ClockTimeThickness
{
get
{
return 2.0;
}
}
public Brush ClockColor
{
get
{
switch (ClockType)
{
case ClockTypes.FixSla:
return new SolidColorBrush(Colors.Cyan);
case ClockTypes.ResponseSla:
return new SolidColorBrush(Colors.DarkMagenta);
case ClockTypes.FixOla:
return new SolidColorBrush(Colors.Yellow);
case ClockTypes.ResponseOla:
return new SolidColorBrush(Colors.DarkSlateGray);
}
return new SolidColorBrush(Colors.Black);
}
}
public IndicatorClock()
{
InitializeComponent();
}
}
}
如何修复此问题以避免GDI泄漏
编辑:根据Clemens的建议调整了代码,但usercontrol仍然是主导者。这是一个MVVM体系结构,我建议您使用MVVM Franmework,如MVVM light,它将有助于避免许多问题并做得更好。
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Priox.Core.Graph.UserControls
{
public partial class IndicatorClock : UserControl
{
public enum ClockTypes
{
None,
FixSla,
ResponseSla,
FixOla,
ResponseOla
};
public static readonly DependencyProperty ClockTypeProperty =
DependencyProperty.Register("ClockType", typeof(ClockTypes),
typeof(IndicatorClock), new FrameworkPropertyMetadata(ClockTypes.None));
public ClockTypes ClockType
{
get { return (ClockTypes)GetValue(ClockTypeProperty); }
set { SetValue(ClockTypeProperty, value); }
}
internal bool IsClockVisible { get; set; }
public Visibility ClockVisibility
{
get
{
if (IsClockVisible)
return System.Windows.Visibility.Visible;
return System.Windows.Visibility.Collapsed;
}
}
public double ClockBorderThickness
{
get
{
return 1.5;
}
}
public double ClockTimeThickness
{
get
{
return 2.0;
}
}
public Brush ClockColor
{
get
{
switch (ClockType)
{
case ClockTypes.FixSla:
return new SolidColorBrush(Colors.Cyan);
case ClockTypes.ResponseSla:
return new SolidColorBrush(Colors.DarkMagenta);
case ClockTypes.FixOla:
return new SolidColorBrush(Colors.Yellow);
case ClockTypes.ResponseOla:
return new SolidColorBrush(Colors.DarkSlateGray);
}
return new SolidColorBrush(Colors.Black);
}
}
public IndicatorClock()
{
InitializeComponent();
}
}
}
使用MVVMLight,您不需要实现INotifyPropertyChanged,框架正在做所有事情
希望这会有所帮助。这是一个MVVM体系结构,我建议您使用MVVM Franmework,如MVVM light,它将有助于避免许多问题并编写更好的代码。 使用MVVMLight,您不需要实现INotifyPropertyChanged,框架正在做所有事情
希望这能有所帮助。好的,我解决了我的问题,它与XAML的外观无关,我查看XAML的原因是因为我使用的所有内存分析器都告诉我这些是问题所在。实际的问题是UserControl被设置为应用程序根本不使用的对象。因此XAML没有被垃圾收集,并以这种方式增加了GDI计数
var source = new HwndSource(new HwndSourceParameters())
{
RootVisual = this
};
好的,我解决了我的问题,它与XAML的外观无关,我之所以查看XAML,是因为我使用的所有内存分析器都告诉我,这就是问题所在。实际的问题是UserControl被设置为应用程序根本不使用的对象。因此XAML没有被垃圾收集,并以这种方式增加了GDI计数
var source = new HwndSource(new HwndSourceParameters())
{
RootVisual = this
};
除此之外,您似乎不会在任何地方触发PropertyChanged事件,在从DependencyObject(如UserControl)派生的类中实现INotifyPropertyChanged也没有任何意义。DependencyObject派生类中声明的属性应该是依赖属性,它们有自己的更改通知机制当用户控件公开可绑定属性时,在该控件中使用code>。通常的基于DataContext的绑定(如
)将不再有效。与其显式设置DataContext,不如在UserControl的XAML中使用RelativeSource绑定,如Fill=“{Binding ClockColor,RelativeSource={RelativeSource AncestorType=UserControl}}”
根据您的建议调整代码,但它仍然显示为支配者。但我不确定我是否做对了。我的评论并不是为了提供解决方案。仅仅说实现INPC(或数据绑定)与您的实际问题没有任何关系。实施它是没有意义的。好吧,我也认为实施INPC是没有用的,但是一些消息来源说这是为了防止GDI泄漏。我没有找到任何其他建议来解决我的问题。无论如何,谢谢。除了您似乎没有在任何地方触发PropertyChanged事件之外,在从DependencyObject(如UserControl)派生的类中实现INotifyPropertyChanged没有任何意义。DependencyObject派生类中声明的属性应该是依赖属性,它们有自己的更改通知机制当用户控件公开可绑定属性时,在该控件中使用code>。通常的基于DataContext的绑定(如
)将不再有效。与其显式设置DataContext,不如在UserControl的XAML中使用RelativeSource绑定,如Fill=“{Binding ClockColor,RelativeSource={RelativeSource AncestorType=UserControl}}”
根据您的建议调整代码,但它仍然显示为支配者。但我不确定我是否做对了。我的评论并不是为了提供解决方案。仅仅说实现INPC(或数据绑定)与您的实际问题没有任何关系。实施它是没有意义的。好吧,我也认为实施INPC是没有用的,但是一些消息来源说这是为了防止GDI泄漏。我没有找到任何其他建议来解决我的问题。无论如何谢谢你