C# 如何仅在一个控件中设置工具提示?
我已经将工具提示用于行为。因此,当单击控件时,将显示工具提示 但是,当更改禁用的控件时,此工具提示不会出现。 因为,未激活鼠标事件。因此,我使用了ContentContorl,它可以在更改禁用时激活鼠标事件 但是,当我在一个网格中有几个控件时,我不知道如何激活唯一的一个控件C# 如何仅在一个控件中设置工具提示?,c#,wpf,C#,Wpf,我已经将工具提示用于行为。因此,当单击控件时,将显示工具提示 但是,当更改禁用的控件时,此工具提示不会出现。 因为,未激活鼠标事件。因此,我使用了ContentContorl,它可以在更改禁用时激活鼠标事件 但是,当我在一个网格中有几个控件时,我不知道如何激活唯一的一个控件 <Window.Resources> <Style TargetType="ContentControl" > <Setter Property="localToolTi
<Window.Resources>
<Style TargetType="ContentControl" >
<Setter Property="localToolTip:ToolTipTouchScreenBehavior.IsEnabled" Value="True"/>
</Style>
<Style TargetType="TextBlock" >
<Setter Property="localToolTip:ToolTipTouchScreenBehavior.IsEnabled" Value="True"/>
</Style>
</Window.Resources>
<ContentControl ToolTip="This is ToolTip5 Test.">
<Grid IsEnabled="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Left" Margin="5" TextWrapping="Wrap" Text="ToolTip Test5" FontSize="25"
ToolTipService.ShowOnDisabled="True" />
<TextBox Grid.Column="1" Width="200" />
</Grid>
</ContentControl>
public class ToolTipTouchScreenBehavior : Behavior<FrameworkElement>
{
public static DependencyProperty IsEnabledProperty =
DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),
typeof(ToolTipTouchScreenBehavior), new FrameworkPropertyMetadata(false, OnIsEnabledChanged));
public static bool GetIsEnabled(DependencyObject uie)
{
return (bool)uie.GetValue(IsEnabledProperty);
}
public static void SetIsEnabled(DependencyObject uie, bool value)
{
uie.SetValue(IsEnabledProperty, value);
}
public static void OnIsEnabledChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs e)
{
UIElement uie = dpo as UIElement;
if (uie != null)
{
var behColl = Interaction.GetBehaviors(uie);
var existingBehavior = behColl.FirstOrDefault(b => b.GetType() ==
typeof(ToolTipTouchScreenBehavior)) as ToolTipTouchScreenBehavior;
if ((bool)e.NewValue == false && existingBehavior != null)
behColl.Remove(existingBehavior);
else if ((bool)e.NewValue == true && existingBehavior == null)
behColl.Add(new ToolTipTouchScreenBehavior());
}
}
Timer timer { get; set; }
ToolTip toolTip { get; set; }
protected override void OnAttached()
{
base.OnAttached();
toolTip = new ToolTip();
timer = new Timer();
timer.Interval = 5000;
timer.Elapsed += OnTimerElapsed;
AssociatedObject.MouseLeave += OnMouseLeave;
AssociatedObject.MouseLeftButtonUp += OnMouseLeftButtonUp;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.MouseLeave -= OnMouseLeave;
AssociatedObject.MouseLeftButtonUp -= OnMouseLeftButtonUp;
}
public void OnMouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
CloseToolTip();
}
public void OnMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
try
{
//var temp = AssociatedObject.ToolTip;
//if (((dynamic)sender).ToolTip != null)
if (AssociatedObject.ToolTip != null)
{
if (AssociatedObject.ToolTip is string)
toolTip.Content = AssociatedObject.ToolTip;
else
toolTip = (ToolTip)AssociatedObject.ToolTip;
//Debug.WriteLine("ToolTip Opened: {0}, ToolTip Value: {1}", toolTip.IsOpen, toolTip.ToolTip);
toolTip.IsOpen = true;
timer.Start();
}
}
catch (Exception ex)
{
throw ex;
}
}
private void CloseToolTip()
{
if (timer.Enabled)
{
timer.Stop();
}
if (toolTip != null)
{
toolTip.IsOpen = false;
}
}
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
Application.Current.Dispatcher.BeginInvoke((Action)CloseToolTip, DispatcherPriority.Send);
}
}
公共类ToolTipTouchScreenBehavior:行为
{
公共静态从属属性IsEnabledProperty=
从属财产。注册(“IsEnabled”),类型为(bool),
typeof(ToolTiptouchScreenBevior),新框架属性元数据(false,OnSenabledChanged));
公共静态bool GetIsEnabled(DependencyObject uie)
{
返回(bool)uie.GetValue(IsEnabledProperty);
}
公共静态无效设置已启用(DependencyObject uie,布尔值)
{
uie.SetValue(IsEnabledProperty,value);
}
公共静态无效OnInsEnabledChanged(DependencyObject dpo、DependencyPropertyChangedEventArgs e)
{
uie元素uie=dpo作为uie元素;
如果(uie!=null)
{
var behColl=Interaction.GetBehaviors(uie);
var existingBehavior=behColl.FirstOrDefault(b=>b.GetType()==
(ToolTipTouchScreenBehavior)作为ToolTipTouchScreenBehavior的类型;
if((bool)e.NewValue==false&&existingBehavior!=null)
behColl.移除(现有行为);
else如果((bool)e.NewValue==true&&existingBehavior==null)
添加(新的ToolTipTouchScreenBehavior());
}
}
计时器{get;set;}
工具提示工具提示{get;set;}
受保护的覆盖无效附加()
{
base.onatached();
工具提示=新工具提示();
定时器=新定时器();
定时器间隔=5000;
timer.appeased+=ontimerecursed;
AssociatedObject.MouseLeave+=OnMouseLeave;
AssociatedObject.MouseLeftButtonUp+=OnMouseLeftButtonUp;
}
附加时受保护的覆盖无效()
{
base.OnDetaching();
AssociatedObject.MouseLeave-=OnMouseLeave;
AssociatedObject.MouseLeftButtonUp-=OnMouseLeftButtonUp;
}
MouseLeave上的公共无效(对象发送方,System.Windows.Input.MouseEventArgs e)
{
关闭工具提示();
}
MouseLeftButtonUp(对象发送方,System.Windows.Input.MouseButtonEventArgs e)上的公共void
{
尝试
{
//var temp=AssociatedObject.ToolTip;
//if(((动态)发送者).工具提示!=null)
如果(AssociatedObject.ToolTip!=null)
{
if(AssociatedObject.ToolTip为字符串)
toolTip.Content=AssociatedObject.toolTip;
其他的
toolTip=(toolTip)AssociatedObject.toolTip;
//WriteLine(“打开的工具提示:{0},工具提示值:{1}”,ToolTip.IsOpen,ToolTip.ToolTip);
toolTip.IsOpen=true;
timer.Start();
}
}
捕获(例外情况除外)
{
掷骰子;
}
}
专用工具提示()
{
如果(计时器已启用)
{
timer.Stop();
}
如果(工具提示!=null)
{
toolTip.IsOpen=false;
}
}
私有void onTimeRecursed(对象发送方,ElapsedEventArgs e)
{
Application.Current.Dispatcher.BeginInvoke((操作)关闭工具提示,DispatcherPriority.Send);
}
}
当我有了以上代码后,我只想为TextBlock添加工具提示。不是文本框
如何将工具提示仅应用于一个特殊控件?如果您的问题与grek40所述相同,则以下是答案: 如果确实希望在禁用父控件时显示工具提示,可以将ToolTipService.ShowOnDisabled属性设置为true。
如果您想对禁用元素的鼠标交互做出反应,可以向装饰器层添加一个可视对象(它将对禁用的基础元素保持启用状态),并在那里捕获输入。下面是一个装饰器的粗略示意图,该装饰器仅对禁用的控件和将装饰器连接到某个框架元素的附加属性执行
MouseLeftButtonUp
上的任意操作(您可能希望改用您的行为)
用法
如果我理解正确,您应该询问如何对禁用控件上的鼠标事件做出反应以激活工具提示?我认为问题的关键在于,不仅要在鼠标悬停时自动显示工具提示,还要处理特殊的输入设备(触摸板),鼠标不会神奇地停留在某些控件上。对于大多数正常的用例来说,提到这个属性还是很好的。哇!!,它很有效,对我很有帮助。非常感谢。@Song如果有帮助的话,你应该把它标记为答案;)
public class DisabledMouseUpAdorner : Adorner
{
private Border _Child;
private Action _OnDisabledMouseUp;
public DisabledMouseUpAdorner(FrameworkElement element, Action onDisabledMouseUp)
: base(element)
{
_OnDisabledMouseUp = onDisabledMouseUp;
_Child = new Border();
_Child.MouseLeftButtonUp += Adorner_Click;
// actually you probably want an invisible adorner, but for demonstration lets add some color
//_Child.Background = new SolidColorBrush(Colors.Transparent);
_Child.Background = new SolidColorBrush(new Color() { A = 20, R = 255, G = 0, B = 0 });
_Child.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
_Child.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
_Child.IsHitTestVisible = !element.IsEnabled;
element.IsEnabledChanged += Adorned_IsEnabledChanged;
AddVisualChild(_Child);
}
void Adorned_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
_Child.IsHitTestVisible = !AdornedElement.IsEnabled;
}
void Adorner_Click(object sender, RoutedEventArgs e)
{
if (_OnDisabledMouseUp != null)
{
_OnDisabledMouseUp();
}
}
protected override int VisualChildrenCount
{ get { return 1; } }
protected override Visual GetVisualChild(int index)
{
if (index != 0) throw new ArgumentOutOfRangeException();
return _Child;
}
protected override Size MeasureOverride(Size constraint)
{
_Child.Measure(constraint);
return base.MeasureOverride(constraint);
}
protected override Size ArrangeOverride(Size finalSize)
{
_Child.Arrange(new Rect(new Point(0, 0), finalSize));
return finalSize;
}
}
public static class Attached
{
public static bool GetToolTipOnClickEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(ToolTipOnClickEnabledProperty);
}
public static void SetToolTipOnClickEnabled(DependencyObject obj, bool value)
{
obj.SetValue(ToolTipOnClickEnabledProperty, value);
}
// Using a DependencyProperty as the backing store for ToolTipOnClickEnabled. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ToolTipOnClickEnabledProperty =
DependencyProperty.RegisterAttached("ToolTipOnClickEnabled", typeof(bool), typeof(Attached), new PropertyMetadata(false, new PropertyChangedCallback(OnToolTipOnClickChanged)));
private static void OnToolTipOnClickChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = d as FrameworkElement;
if (element != null)
{
if (element.IsLoaded)
{
if ((bool)e.NewValue == true)
{
AddOverlay(element);
}
else
{
RemoveOverlay(element);
}
}
else
{
element.Loaded -= Element_Loaded;
element.Loaded += Element_Loaded;
}
}
}
private static void Element_Loaded(object sender, RoutedEventArgs e)
{
var elem = sender as FrameworkElement;
elem.Loaded -= Element_Loaded;
if (GetToolTipOnClickEnabled(elem))
{
AddOverlay(elem);
}
else
{
RemoveOverlay(elem);
}
}
private static void RemoveOverlay(FrameworkElement element)
{
var adl = AdornerLayer.GetAdornerLayer(element);
var ad = adl.GetAdorners(element);
foreach (var item in ad)
{
if (item is DisabledMouseUpAdorner) adl.Remove(item);
}
}
private static void AddOverlay(FrameworkElement element)
{
var a = AdornerLayer.GetAdornerLayer(element);
if (a != null)
{
a.Add(new DisabledMouseUpAdorner(element, () => ClickHandler(element)));
}
else
{
}
}
// whatever you actually want to do when the adorner triggers
private static void ClickHandler(FrameworkElement element)
{
if (element.ToolTip == null)
{
return;
}
var tt = element.ToolTip as ToolTip ?? new ToolTip() { Content = element.ToolTip, StaysOpen = false };
tt.IsOpen = true;
}
}
<TextBlock Text="ToolTip Test5" FontSize="25"
ToolTip="Shows on click when disabled"
local:Attached.ToolTipOnClickEnabled="True" />