在Eclipse中,我可以通过在F2打开时按F2来聚焦工具提示。它转换为一个单独的弹出窗口,只要我想要保持打开状态,我就可以调整它。
如何让它在WPF中运行?
工具提示在5秒后关闭,这对大多数人来说都是有意义的。默认情况下,我没有工具提示永远保持打开状态,但有时我想阅读时间超过5秒。我喜欢按一个键让工具提示粘到GUI上的想法,直到我手动关闭它。
我希望使用ToolTip可以实现这一点,因为我不想用自定义的Popup行为替换GUI中的每个工具提示......
答案 0 :(得分:1)
由于这给了我一个不眠之夜,我现在和永远地做了一个(或多或少)简单的通用方法来解决这个问题。
以下解决方案基于Style-Behaviors,它需要一些准备,因为没有任何内置。
让样式接受行为
/// <summary>
/// Collection for <see cref="StylizedBehaviors"/>
/// </summary>
public class StylizedBehaviorCollection : FreezableCollection<Behavior> {
protected override Freezable CreateInstanceCore() {
return new StylizedBehaviorCollection();
}
}
/// <summary>
/// This Behavior allows us to set Behaviors in Styles for a Generic approach
/// </summary>
public class StylizedBehaviors {
private static readonly DependencyProperty OriginalBehaviorProperty = DependencyProperty.RegisterAttached(@"OriginalBehaviorInternal", typeof(Behavior), typeof(StylizedBehaviors), new UIPropertyMetadata(null));
public static readonly DependencyProperty BehaviorsProperty = DependencyProperty.RegisterAttached(
@"Behaviors",
typeof(StylizedBehaviorCollection),
typeof(StylizedBehaviors),
new FrameworkPropertyMetadata(null, OnPropertyChanged));
public static StylizedBehaviorCollection GetBehaviors(DependencyObject uie) {
return (StylizedBehaviorCollection)uie.GetValue(BehaviorsProperty);
}
public static void SetBehaviors(DependencyObject uie, StylizedBehaviorCollection value) {
uie.SetValue(BehaviorsProperty, value);
}
private static Behavior GetOriginalBehavior(DependencyObject obj) {
return obj.GetValue(OriginalBehaviorProperty) as Behavior;
}
private static int GetIndexOf(BehaviorCollection itemBehaviors, Behavior behavior) {
var index = -1;
var orignalBehavior = GetOriginalBehavior(behavior);
for (var i = 0; i < itemBehaviors.Count; i++) {
var currentBehavior = itemBehaviors[i];
if (currentBehavior == behavior || currentBehavior == orignalBehavior) {
index = i;
break;
}
var currentOrignalBehavior = GetOriginalBehavior(currentBehavior);
if (currentOrignalBehavior != behavior && currentOrignalBehavior != orignalBehavior)
continue;
index = i;
break;
}
return index;
}
private static void OnPropertyChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs e) {
var uie = dpo as UIElement;
if (uie == null) {
return;
}
var itemBehaviors = Interaction.GetBehaviors(uie);
var newBehaviors = e.NewValue as StylizedBehaviorCollection;
var oldBehaviors = e.OldValue as StylizedBehaviorCollection;
if (newBehaviors == oldBehaviors) {
return;
}
if (oldBehaviors != null) {
foreach (var index in oldBehaviors.Select(behavior => GetIndexOf(itemBehaviors, behavior)).Where(index => index >= 0)) {
itemBehaviors.RemoveAt(index);
}
}
if (newBehaviors == null)
return;
foreach (var behavior in newBehaviors) {
var index = GetIndexOf(itemBehaviors, behavior);
if (index >= 0)
continue;
var clone = (Behavior)behavior.Clone();
SetOriginalBehavior(clone, behavior);
itemBehaviors.Add(clone);
}
}
private static void SetOriginalBehavior(DependencyObject obj, Behavior value) {
obj.SetValue(OriginalBehaviorProperty, value);
}
}
我们想要的热键行为
public class ToolTipHotKeyBehavior : Behavior<Control> {
public Key HotKey {
get {
return (Key)this.GetValue(HotKeyProperty);
}
set {
this.SetValue(HotKeyProperty, value);
}
}
public static readonly DependencyProperty HotKeyProperty =
DependencyProperty.Register("HotKey", typeof(Key), typeof(ToolTipHotKeyBehavior), new PropertyMetadata(Key.F1));
protected override void OnAttached() {
this.AssociatedObject.Loaded += this.TargetLoaded;
base.OnAttached();
}
private void TargetLoaded(object sender, RoutedEventArgs e) {
var ctrl = (sender as Control);
if (ctrl == null)
return;
ctrl.PreviewKeyDown += (o, args) => {
if (args.Key != this.HotKey)
return;
if (ctrl.ToolTip.GetType() != typeof(ToolTip))
ToolTipService.SetToolTip(ctrl, new ToolTip { Content = ctrl.ToolTip });
(ctrl.ToolTip as ToolTip).IsOpen = !(ctrl.ToolTip as ToolTip).IsOpen;
};
}
}
在XAML中使用示例
<Window.Resources>
<Style TargetType="{x:Type PasswordBox}">
<Setter Property="Background" Value="Green"></Setter>
<Setter Property="local:StylizedBehaviors.Behaviors">
<Setter.Value>
<local:StylizedBehaviorCollection>
<local:ToolTipHotKeyBehavior />
</local:StylizedBehaviorCollection>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<PasswordBox Margin="10" VerticalAlignment="Center" ToolTip="Enter Password"/>
<Button Content="hello" ToolTip="This is a Button">
<Button.Style>
<Style>
<Style.Setters>
<Setter Property="local:StylizedBehaviors.Behaviors">
<Setter.Value>
<local:StylizedBehaviorCollection>
<local:ToolTipHotKeyBehavior HotKey="F3" />
</local:StylizedBehaviorCollection>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</Button.Style>
</Button>
</StackPanel>
<强>封闭强>
不幸的是,这可能是执行此类操作的最简单和通用的方法。如您所见,行为可以应用于子类Control
的所有内容
此外,您可以在每个控件/控件类型上设置不同的热键(如果需要,也可以绑定它)
注意强>
此示例基于以下事实:您使用字符串作为初始工具提示,因为行为将其转换为真实的工具提示以便能够打开/关闭它。
我希望这符合您的需求。干杯