-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で添付された動作を使用する例を示します。 この場合、2つのコントロールは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

私はあなたと同じ方法で使用しますが、値を使用しないためバインディングは使用しません(あなたは '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

関連する問題