假设我在一个需要使用超链接控件呈现的类上有一个属性。超链接将绑定到视图模型上的命令,以便单击它可触发某些操作。像这样:
<Style x:Key="HyperlinkStyle" TargetType="{x:Type igDP:CellValuePresenter}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type igDP:CellValuePresenter}">
<Border BorderBrush="{StaticResource DataGridCellOuterBorder}" BorderThickness="1,0,0,0" >
<TextBlock Margin="5">
<Hyperlink
Command="{Binding ElementName=dataGrid, Path=DataContext.Commands[GetSolutionSummaryCmd], Mode=OneTime}"
CommandParameter="{Binding Path=(igDP:DataRecord.DataItem), Mode=OneTime}">
<TextBlock Text="{TemplateBinding Value}"/>
</Hyperlink>
</TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
如何确保从网格中删除数据项时,dataGrid.DataContext.Command [GetSolutionSummaryCmd],ICommand的实现和带有超链接列的每个数据记录之间的绑定被破坏,因此数据项可以是垃圾收集?否则,我发现这里存在泄漏内存的可能性。
此外,GetSolutionSummaryCmd是RelayCommand的实例,如下所示:
public class RelayCommand : ICommand
{
readonly protected Predicate<object> _canExecute;
readonly protected Action<object> _execute;
public RelayCommand(Predicate<object> canExecute, Action<object> execute)
: this(canExecute, execute, true)
{
}
public RelayCommand(Predicate<object> canExecute, Action<object> execute, bool isCommandAllowed)
{
_canExecute = canExecute;
_execute = execute;
IsAllowed = isCommandAllowed;
}
public void RaiseCanExecuteChanged()
{
if (this.CanExecuteChanged != null)
this.CanExecuteChanged(this, EventArgs.Empty);
}
#region ICommand Members
public virtual bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public event EventHandler CanExecuteChanged;
public virtual void Execute(object parameter)
{
_execute(parameter);
}
#endregion
}
与this相反,我需要能够引发CanExecuteChanged。
答案 0 :(得分:2)
我使用了here建议来实现此问题的解决方案。泄漏肯定是由上述Style中使用的超链接元素引起的。 ANTS探查器在内存快照之间为System.Windows.EffectiveValueEntry []指示了一个正实例计数。当我查看此类的对象引用图时,始终会引用链中的超链接实例。
更改了基础数据,以便在单击时始终可以执行超链接。这意味着不必引发ICommand的CanExecuteChanged事件,允许我像这样定义某种NoReferenceRelayCommand类:
public class NoReferenceRelayCommand : ICommand
{
protected readonly Action<object> _execute;
public NoReferenceRelayCommand(Action<object> execute)
{
Guard.ThrowIfArgumentIsNull(execute);
_execute = execute;
}
#region ICommand Members
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged
{
add { }
remove { }
}
public void Execute(object parameter)
{
_execute(parameter);
}
#endregion
}
超过10小时的性能分析解决方案显示System.Windows.EffectiveValueEntry的实例编号不会增加。