-1

UIElement의 MouseEnter 및 MouseLeave 이벤트를 처리하는 WPF 첨부 동작이 있습니다. WeakEventManager를 사용하도록 전환하여 메모리 누수를 방지하려고 시도했지만 이제는 코드가 더 이상 이벤트를 처리하지 않습니다. 내가 사용하는 경우WeakEventManager가 연결된 동작에서 이벤트를 처리하지 못합니다.

(아래 참조) :

_control.MouseEnter += OnMouseEnter; 
_control.MouseLeave += OnMouseLeave; 

코드가 이벤트를 처리합니다. 내가 사용하는 경우

(아래 참조) :

WeakEventManager<UIElement, RoutedEventArgs>.AddHandler(_control, "MouseEnter", OnMouseEnter); 
    WeakEventManager<UIElement, RoutedEventArgs>.AddHandler(_control, "MouseLeave", OnMouseLeave); 

코드가 이벤트를 처리하지 않습니다.

첨부 된 동작에서 WeakEventManager를 사용하여 이벤트를 처리하려면 어떻게해야합니까?

다음은 XAML에서 연결된 동작을 사용하는 방법의 예입니다. 이 경우 두 컨트롤은 TreeView 컨트롤에 노드로 나타납니다. 나는 많은 다른 컨트롤과 연결된 동작을 사용했지만 작동하지 않습니다. 여기

<HierarchicalDataTemplate x:Key="EquipmentUnitTemplate" > 
    <StackPanel 
     Orientation="Horizontal"> 
     <controls:EquipmentUnitBillboard 
     Width="22" 
     Height="20" 
     VerticalAlignment="Center" 
     Style="{DynamicResource TreeViewNavigatorEquipmentUnitBillboardStyle}" 
     behaviours:ToolTipEquipmentUnitHelper.TooltipMemberBinding="{Binding EquipmentUnitModel}" 
     behaviours:ContextMenuEquipmentUnitHelper.ContextMenuMemberBinding="{Binding EquipmentUnitModel}" 
     Visibility="{Binding HasIcon, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverterCollapsed}}" 
     IconType="{Binding IconId, Mode=OneWay}"/> 
     <Label 
     Margin="5,0,0,0" 
     Padding="0,0,0,0" 
     VerticalAlignment="Center" 
     Style="{DynamicResource LabelInTreeStyle}" 
     behaviours:ToolTipEquipmentUnitHelper.TooltipMemberBinding="{Binding EquipmentUnitModel}" 
     behaviours:ContextMenuEquipmentUnitHelper.ContextMenuMemberBinding="{Binding EquipmentUnitModel}" 
     Content="{Binding DisplayName}" 
     FontWeight="Bold" 
     /> 
    </StackPanel> 
    </HierarchicalDataTemplate> 

제거 불필요한 대부분의 코드에 첨부 된 동작입니다 :

public class ToolTipHelper 
{ 
private readonly UIElement _control = null; 

public ToolTipHelper(UIElement control) 
{ 
    this._control = control; 
} 

public static readonly DependencyProperty TooltipMemberBindingProperty 
    = DependencyProperty.RegisterAttached("TooltipMemberBinding", typeof(object), typeof(ToolTipHelper), new PropertyMetadata(null, OnTooltipMemberBindingChanged)); 

public static void SetTooltipMemberBinding(DependencyObject dependencyObject, object tooltipMember) 
{ 
    dependencyObject.SetValue(TooltipMemberBindingProperty, tooltipMember); 
} 

public static object GetTooltipMemberBinding(DependencyObject dependencyObject) 
{ 
    return (object)dependencyObject.GetValue(TooltipMemberBindingProperty); 
} 

private static void OnTooltipMemberBindingChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
{ 
    var control = dependencyObject as UIElement; 
    if (control != null) 
    { 
    if ((object)e.NewValue != null) 
    { 
     var behavior = new ToolTipHelper(control); 
     behavior.Attach(); 
    } 

    if ((object)e.OldValue != null) 
    { 
     var behavior = new ToolTipHelper(control); 
     behavior.Detach(); 
    } 
    } 
} 

private void Attach() 
{ 
    if (_control != null) 
    { 
    var container = ServiceLocator.Current.GetInstance<IUnityContainer>(); 
    var applicationServices = container.Resolve<IApplicationServices>(); 
    var applicationSettings = container.Resolve<IApplicationSettings>(); 
    var realtimeObjectModel = container.Resolve<IRealtimeObjectModel>(); 
    var kpiEngine = container.Resolve<IKPIEngine>(); 
    var wcmSettings = container.Resolve<WencoConfigurationSettingsModel>(); 

    var val = _control.GetValue(TooltipMemberBindingProperty); 

    if (val is HaulingUnit) 
    { 
     HaulingUnitToolTipViewModel huvm = new HaulingUnitToolTipViewModel(applicationServices, applicationSettings, realtimeObjectModel, wcmSettings, val as HaulingUnit); 
     _control.SetValue(RadToolTipService.ToolTipContentProperty, huvm); 

     DataTemplate template = (DataTemplate)Application.Current.FindResource("HaulingUnitTooltipTemplate"); 
     _control.SetValue(RadToolTipService.ToolTipContentTemplateProperty, template); 

    } 
    else if (val is LoadingUnit) 
    { 
     LoadingUnitToolTipViewModel luvm = new LoadingUnitToolTipViewModel(applicationServices, applicationSettings, realtimeObjectModel, kpiEngine, wcmSettings, val as LoadingUnit); 
     _control.SetValue(RadToolTipService.ToolTipContentProperty, luvm); 

     DataTemplate template = (DataTemplate)Application.Current.FindResource("LoadingUnitTooltipTemplate"); 
     _control.SetValue(RadToolTipService.ToolTipContentTemplateProperty, template); 
    } 
    else if (val is DrillUnit) 
    { 
     DrillUnitToolTipViewModel luvm = new DrillUnitToolTipViewModel(applicationServices, applicationSettings, realtimeObjectModel, wcmSettings, val as DrillUnit); 
     _control.SetValue(RadToolTipService.ToolTipContentProperty, luvm); 

     DataTemplate template = (DataTemplate)Application.Current.FindResource("DrillUnitTooltipTemplate"); 
     _control.SetValue(RadToolTipService.ToolTipContentTemplateProperty, template); 
    } 
    else if (val is ScraperUnit) 
    { 
     ScraperUnitToolTipViewModel scvm = new ScraperUnitToolTipViewModel(applicationServices, applicationSettings, realtimeObjectModel, wcmSettings, val as ScraperUnit); 
     _control.SetValue(RadToolTipService.ToolTipContentProperty, scvm); 

     DataTemplate template = (DataTemplate)Application.Current.FindResource("ScraperUnitTooltipTemplate"); 
     _control.SetValue(RadToolTipService.ToolTipContentTemplateProperty, template); 
    } 
    else if (val is AuxiliaryUnit) 
    { 
     AuxiliaryUnitToolTipViewModel auvm = new AuxiliaryUnitToolTipViewModel(applicationServices, applicationSettings, realtimeObjectModel, wcmSettings, val as AuxiliaryUnit); 
     _control.SetValue(RadToolTipService.ToolTipContentProperty, auvm); 

     DataTemplate template = (DataTemplate)Application.Current.FindResource("OtherUnitTooltipTemplate"); 
     _control.SetValue(RadToolTipService.ToolTipContentTemplateProperty, template); 
    } 
    else if (val is FuelTruckUnit) 
    { 
     FuelTruckUnitToolTipViewModel auvm = new FuelTruckUnitToolTipViewModel(applicationServices, applicationSettings, realtimeObjectModel, wcmSettings, val as FuelTruckUnit); 
     _control.SetValue(RadToolTipService.ToolTipContentProperty, auvm); 

     DataTemplate template = (DataTemplate)Application.Current.FindResource("OtherUnitTooltipTemplate"); 
     _control.SetValue(RadToolTipService.ToolTipContentTemplateProperty, template); 
    } 
    else if (val is CrusherUnit) 
    { 
     CrusherUnitToolTipViewModel auvm = new CrusherUnitToolTipViewModel(applicationServices, applicationSettings, realtimeObjectModel, wcmSettings, val as CrusherUnit); 
     _control.SetValue(RadToolTipService.ToolTipContentProperty, auvm); 

     DataTemplate template = (DataTemplate)Application.Current.FindResource("OtherUnitTooltipTemplate"); 
     _control.SetValue(RadToolTipService.ToolTipContentTemplateProperty, template); 
    } 
    //else if (val is DumpLocationDispatchConfigurationViewModel) 
    //{ 

    //} 

    int initial = Convert.ToInt32(SharedConstants.TooltipInitialShowDelayDuration.TotalMilliseconds); 
    _control.SetValue(RadToolTipService.InitialShowDelayProperty, initial); 
    int between = Convert.ToInt32(SharedConstants.TooltipBetweenShowDelayDuration.TotalMilliseconds); 
    _control.SetValue(RadToolTipService.BetweenShowDelayProperty, between); 
    int duration = Convert.ToInt32(applicationSettings.ProgramSettings.ToolTips.ToolTipOpenDuration.TotalMilliseconds); 
    _control.SetValue(RadToolTipService.ShowDurationProperty, duration); 

    // using this code the event never gets handled 
    WeakEventManager<UIElement, RoutedEventArgs>.AddHandler(_control, "MouseEnter", OnMouseEnter); 
    WeakEventManager<UIElement, RoutedEventArgs>.AddHandler(_control, "MouseLeave", OnMouseLeave); 
    // if I uncomment these two lines the event gets handled. 
    //_control.MouseEnter += OnMouseEnter; 
    //_control.MouseLeave += OnMouseLeave; 
    } 
} 

private void Detach() 
{ 
    if (_control != null) 
    { 
    WeakEventManager<UIElement, RoutedEventArgs>.RemoveHandler(_control, "MouseEnter", OnMouseEnter); 
    WeakEventManager<UIElement, RoutedEventArgs>.RemoveHandler(_control, "MouseLeave", OnMouseLeave); 
    //_control.MouseEnter -= OnMouseEnter; 
    //_control.MouseLeave -= OnMouseLeave; 
    } 
} 

private void OnMouseEnter(object sender, RoutedEventArgs routedEventArgs) 
{ 
    try 
    { 
    if ((sender is UIElement)) 
    { 
     UIElement control = sender as UIElement; 
    } 
    } 
    catch (Exception ex) 
    { 
    } 
} 

private void OnMouseLeave(object sender, RoutedEventArgs routedEventArgs) 
{ 
    try 
    { 
    if ((sender is UIElement)) 
    { 
     UIElement control = sender as UIElement; 
    } 
    } 
    catch (Exception ex) 
    { 
    } 
} 

}

+0

난 당신의 코드를 붙여 복사하는 경우 - 그것은 나를 위해 잘 작동하고 핸들러가 발생합니다. 그걸 재현하려면 더 많은 정보가 필요하다. (제거한 불필요한 코드는 예를 들어 실제로 불필요하지 않다.) – Evk

+0

감사합니다. 나는 Attach() 메소드의 코드를 도움이되고 사용법 XAML 예제에 추가했다. 아마도이 문제를 해결하는 데 도움이 될 수있는 XAML의 연결된 동작을 어떻게 사용했는지 보여 주시겠습니까? – Zamboni

+0

당신이하는 것과 같은 방식으로 사용하지만, 어쨌든 값을 사용하지 않기 때문에 Binding을 사용하지 않습니다. (if ((object) e.NewValue! = null)'나는 그렇게하지 않습니다. 왜 어떤 값을 건네 주면 (예 :'Behaviors : ToolTipEquipmentUnitHelper.TooltipMemberBinding = "test"') 나에게 잘 돌아 간다. 문제를 재현 할 수있는 최소한의 예제를 찾아 보자. – Evk

답변

1

컨트롤이로드 될 때까지 당신이 처리기를 추가하기 전에 기다려야합니다.

이 작동 :

private void Attach() 
{ 
    if (_control != null) 
    { 
     FrameworkElement fe = _control as FrameworkElement; 
     if (fe != null) 
     { 
      if (fe.IsLoaded) 
      { 
       WeakEventManager<UIElement, RoutedEventArgs>.AddHandler(_control, "MouseEnter", OnMouseEnter); 
       WeakEventManager<UIElement, RoutedEventArgs>.AddHandler(_control, "MouseLeave", OnMouseLeave); 
      } 
      else 
      { 
       fe.Loaded += Fe_Loaded; 
      } 
     } 
    } 
} 

private void Fe_Loaded(object sender, RoutedEventArgs e) 
{ 
    WeakEventManager<UIElement, RoutedEventArgs>.AddHandler(_control, "MouseEnter", OnMouseEnter); 
    WeakEventManager<UIElement, RoutedEventArgs>.AddHandler(_control, "MouseLeave", OnMouseLeave); 
} 

private void Detach() 
{ 
    if (_control != null) 
    { 
     FrameworkElement fe = _control as FrameworkElement; 
     if (fe != null) 
      fe.Loaded += Fe_Loaded; 
     WeakEventManager<UIElement, RoutedEventArgs>.RemoveHandler(_control, "MouseEnter", OnMouseEnter); 
     WeakEventManager<UIElement, RoutedEventArgs>.RemoveHandler(_control, "MouseLeave", OnMouseLeave); 
    } 
} 
+0

감사합니다. 컨트롤 컨트롤이로드되지 않았습니다. 컨트롤로드를 기다리면서 코드가 이벤트를 포착하지 못하는 이유를 해결했습니다. – Zamboni