ラベルのツールチップがあり、ユーザーがマウスを別のコントロールに移動するまで、ラベルを開いたままにしておきたいです。
ツールチップで次のプロパティを試しました。
StaysOpen="True"
と
ToolTipService.ShowDuration = "60000"
ただし、どちらの場合も、ツールチップは正確に5秒間しか表示されません。
これらの値が無視されるのはなぜですか?
これを1つのツールチップだけに設定する場合は、次のように、ツールチップを持つオブジェクトの期間を設定します。
<Label ToolTipService.ShowDuration="12000" Name="lblShowTooltip" Content="Shows tooltip">
<Label.ToolTip>
<ToolTip>
<TextBlock>Hello world!</TextBlock>
</ToolTip>
</Label.ToolTip>
</Label>
この設計が選択されたのは、異なるコントロールで異なるタイムアウトを使用して同じツールチップを使用できるためだと思います。
アプリ全体でこれをグローバルに使用する場合は、承認された回答を参照してください。
このコードを初期化セクションに入れるだけです。
ToolTipService.ShowDurationProperty.OverrideMetadata(
typeof(DependencyObject), new FrameworkPropertyMetadata(Int32.MaxValue));
これも今夜私を夢中にさせていました。ToolTip
この問題を処理するためにサブクラスを作成しました。私にとって、.NET 4.0では、ToolTip.StaysOpen
プロパティは「実際に」開いたままではありません。
以下のクラスでは、propertyToolTipEx.IsReallyOpen
の代わりにnewpropertyを使用しますToolTip.IsOpen
。あなたはあなたが望むコントロールを手に入れるでしょう。呼び出しを介してDebug.Print()
、デバッガーの出力ウィンドウで何回this.IsOpen = false
呼び出されたかを確認できます。そんなにStaysOpen
、または私は言うべき"StaysOpen"
ですか?楽しみ。
public class ToolTipEx : ToolTip
{
static ToolTipEx()
{
IsReallyOpenProperty =
DependencyProperty.Register(
"IsReallyOpen",
typeof(bool),
typeof(ToolTipEx),
new FrameworkPropertyMetadata(
defaultValue: false,
flags: FrameworkPropertyMetadataOptions.None,
propertyChangedCallback: StaticOnIsReallyOpenedChanged));
}
public static readonly DependencyProperty IsReallyOpenProperty;
protected static void StaticOnIsReallyOpenedChanged(
DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ToolTipEx self = (ToolTipEx)o;
self.OnIsReallyOpenedChanged((bool)e.OldValue, (bool)e.NewValue);
}
protected void OnIsReallyOpenedChanged(bool oldValue, bool newValue)
{
this.IsOpen = newValue;
}
public bool IsReallyOpen
{
get
{
bool b = (bool)this.GetValue(IsReallyOpenProperty);
return b;
}
set { this.SetValue(IsReallyOpenProperty, value); }
}
protected override void OnClosed(RoutedEventArgs e)
{
System.Diagnostics.Debug.Print(String.Format(
"OnClosed: IsReallyOpen: {0}, StaysOpen: {1}", this.IsReallyOpen, this.StaysOpen));
if (this.IsReallyOpen && this.StaysOpen)
{
e.Handled = true;
// We cannot set this.IsOpen directly here. Instead, send an event asynchronously.
// DispatcherPriority.Send is the highest priority possible.
Dispatcher.CurrentDispatcher.BeginInvoke(
(Action)(() => this.IsOpen = true),
DispatcherPriority.Send);
}
else
{
base.OnClosed(e);
}
}
}
小さな暴言:DependencyProperty
サブクラスの変更を受け入れる/拒否する/調整できるように、Microsoftがプロパティ(ゲッター/セッター)を仮想化しないのはなぜですか?またはvirtual OnXYZPropertyChanged
、すべてのために作成しDependencyProperty
ますか?うーん。
- -編集 - -
上記の私の解決策は、XAMLエディターでは奇妙に見えます-ツールチップは常に表示され、Visual Studioの一部のテキストをブロックします!
この問題を解決するためのより良い方法は次のとおりです。
一部のXAML:
<!-- Need to add this at top of your XAML file:
xmlns:System="clr-namespace:System;assembly=mscorlib"
-->
<ToolTip StaysOpen="True" Placement="Bottom" HorizontalOffset="10"
ToolTipService.InitialShowDelay="0" ToolTipService.BetweenShowDelay="0"
ToolTipService.ShowDuration="{x:Static Member=System:Int32.MaxValue}"
>This is my tooltip text.</ToolTip>
いくつかのコード:
// Alternatively, you can attach an event listener to FrameworkElement.Loaded
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// Be gentle here: If someone creates a (future) subclass or changes your control template,
// you might not have tooltip anymore.
ToolTip toolTip = this.ToolTip as ToolTip;
if (null != toolTip)
{
// If I don't set this explicitly, placement is strange.
toolTip.PlacementTarget = this;
toolTip.Closed += new RoutedEventHandler(OnToolTipClosed);
}
}
protected void OnToolTipClosed(object sender, RoutedEventArgs e)
{
// You may want to add additional focus-related tests here.
if (this.IsKeyboardFocusWithin)
{
// We cannot set this.IsOpen directly here. Instead, send an event asynchronously.
// DispatcherPriority.Send is the highest priority possible.
Dispatcher.CurrentDispatcher.BeginInvoke(
(Action)delegate
{
// Again: Be gentle when using this.ToolTip.
ToolTip toolTip = this.ToolTip as ToolTip;
if (null != toolTip)
{
toolTip.IsOpen = true;
}
},
DispatcherPriority.Send);
}
}
ToolTip
結論:クラスと。について何かが異なりますContextMenu
。どちらにも、のような「サービス」クラスがToolTipService
ありContextMenuService
、特定のプロパティを管理し、Popup
表示中に「秘密の」親コントロールとして使用します。最後に、Web上のすべてのXAMLToolTipの例がクラスToolTip
を直接使用していないことに気付きました。代わりに、sを埋め込んでいStackPanel
ますTextBlock
。あなたに言わせること:「うーん...」
ツールチップは、事前定義されたUI標準の方法でポップアップを使用していると想定しているため、ツールチップの代わりにポップアップを使用することをお勧めします。
StaysOpenが機能しない理由はわかりませんが、ShowDurationはMSDNに記載されているように機能します。これは、ツールチップが表示されたときに表示される時間です。違いを確認するには、少量(たとえば、500ミリ秒)に設定します。
あなたの場合の秘訣は「最後のホバーコントロール」状態を維持することですが、それができたら、1つのポップアップを使用している場合は、配置ターゲットとコンテンツを動的に(手動またはバインディングを介して)変更するのはかなり簡単です。または、複数を使用している場合は、最後に表示されたポップアップを非表示にします。
ウィンドウのサイズ変更と移動(ポップアップはコンテナと一緒に移動しない)に関しては、ポップアップに関するいくつかの落とし穴があります。そのため、動作を微調整する際にも、このことを念頭に置いておくとよいでしょう。詳細については、このリンクを参照してください。
HTH。
の特定の要素のみWindow
が実質的に無期限ToolTip
の期間を持つように指定する場合は、それらの要素に対してを定義できStyle
ます。これはそのようなものを持ってWindow.Resources
いるStyle
ためのものです:Button
ToolTip
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
...>
...
<Window.Resources>
<Style x:Key="ButtonToolTipIndefinate" TargetType="{x:Type Button}">
<Setter Property="ToolTipService.ShowDuration"
Value="{x:Static Member=sys:Int32.MaxValue}"/>
</Style>
...
</Window.Resources>
...
<Button Style="{DynamicResource ButtonToolTipIndefinate}"
ToolTip="This should stay open"/>
<Button ToolTip="This Should disappear after the default time.">
...
に追加Style.Resources
して、表示Style
される外観を変更することもできToolTip
ます。次に例を示します。
<Style x:Key="ButtonToolTipTransparentIndefinate" TargetType="{x:Type Button}">
<Style.Resources>
<Style x:Key="{x:Type ToolTip}" TargetType="{x:Type ToolTip}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="HasDropShadow" Value="False"/>
</Style>
</Style.Resources>
<Setter Property="ToolTipService.ShowDuration"
Value="{x:Static Member=sys:Int32.MaxValue}"/>
</Style>
注:これを行ったときは、で使用BasedOn
したStyle
ので、通常のカスタムコントロールのバージョンに対して定義された他のすべてToolTip
が適用されます。
先日だけWPFツールチップと格闘していました。それ自体が現れたり消えたりするのを止めることはできないように思われるので、結局私はOpened
イベントを処理することにしました。たとえば、コンテンツが含まれていない限り、イベントが開かないようにしたかったので、Opened
イベントを処理してから、次のようにしました。
tooltip.IsOpen = (tooltip.Content != null);
それはハックですが、うまくいきました。
おそらく、同様にClosed
イベントを処理して、再度開くように指示して、イベントを表示したままにすることができます。
完全を期すために:コードでは次のようになります。
ToolTipService.SetShowDuration(element, 60000);
また、ツールチップに他のコントロールを配置したい場合は、ツールチップ自体がフォーカスを取得できるため、フォーカスできません。だからミカタンが言ったように、あなたのベストショットはポップアップです。
同じコードで問題を修正しました。
ToolTipService.ShowDurationProperty.OverrideMetadata(typeof(DependencyObject)、new FrameworkPropertyMetadata(Int32.MaxValue));
ToolTipService.ShowDurationProperty.OverrideMetadata(
typeof(DependencyObject), new FrameworkPropertyMetadata(Int32.MaxValue));
それは私のために働いています。この行をクラスコンストラクターにコピーします。