Стиль всплывающей подсказки в Silverlight
Я хочу создать стиль всплывающей подсказки Silverlight, но не хочу использовать текстовый блок, потому что содержимое всплывающей подсказки может быть изображением или чем-то еще. Поэтому я использую ContentPresenter. Моя проблема заключается в том, как установить MaxWidth и принудительно TextWrapping, когда содержимое является текстом. Это то, что я до сих пор:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
<Style TargetType="ToolTip">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border BorderBrush="DimGray" BorderThickness="1" CornerRadius="5" Background="WhiteSmoke" Opacity="0.8"
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,10,0,-5" Width="Auto">
<Border.Effect>
<DropShadowEffect BlurRadius="16" ShadowDepth="8" Direction="-45" Color="Black" Opacity="0.6"/>
</Border.Effect>
<Grid>
<ContentPresenter Content="{TemplateBinding Content}" Margin="3"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
2 ответа
Нам нужно было сделать то же самое и попробовать несколько подходов, прежде чем перейти к следующему решению. Проблема в том, что когда ToolTip.Content является строкой, вам нужно показать всплывающую подсказку с помощью TextBlock. Когда ToolTip.Content не является строкой, вам нужно использовать ContentPresenter. Таким образом, мы в итоге определили ControlTemplate, который имеет оба, и мы показываем / скрываем соответствующий в зависимости от типа ToolTip.Content. Этот подход применяется ко всем подсказкам в приложении:
В этом помогает следующий класс конвертера:
public class TooltipContentVisibilityConverter : IValueConverter
{
public Visibility VisibilityWhenToolTipContentIsAString { get; set; }
public Visibility VisibilityWhenToolTipContentIsNotAString { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var toolTip = value as ToolTip;
if (toolTip != null && toolTip.Content is string)
{
return VisibilityWhenToolTipContentIsAString;
}
return VisibilityWhenToolTipContentIsNotAString;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Затем в вашем App.xaml вы определяете следующее.
<Converter:TooltipContentVisibilityConverter VisibilityWhenToolTipContentIsAString="Visible" VisibilityWhenToolTipContentIsNotAString="Collapsed" x:Key="tooltipStringContentVisibilityConverter" />
<Converter:TooltipContentVisibilityConverter VisibilityWhenToolTipContentIsAString="Collapsed" VisibilityWhenToolTipContentIsNotAString="Visible" x:Key="tooltipNonStringContentVisibilityConverter" />
<Style TargetType="ToolTip">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border CornerRadius="0" Background="{TemplateBinding Background}" BorderBrush="Black" BorderThickness="1" Padding="4">
<StackPanel Orientation="Vertical">
<TextBlock Text="{TemplateBinding Content}" TextWrapping="Wrap" MaxWidth="300"
Visibility="{Binding RelativeSource={RelativeSource AncestorType=ToolTip},Converter={StaticResource tooltipStringContentVisibilityConverter}}"/>
<ContentPresenter Content="{TemplateBinding Content}"
Visibility="{Binding RelativeSource={RelativeSource AncestorType=ToolTip},Converter={StaticResource tooltipNonStringContentVisibilityConverter}}"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Кажется, это немного неуклюжий способ решить эту проблему, но он работает, и мы еще не нашли лучшего решения.
Я нашел один способ сделать это: создать 2 стиля подсказок - один для текста, а другой для всего остального, например:
<Style x:Key="TooltipStyleForText" TargetType="ToolTip">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border BorderBrush="DimGray" BorderThickness="1" CornerRadius="5" Background="WhiteSmoke" Opacity="0.8"
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,10,0,-5" Width="Auto">
<Border.Effect>
<DropShadowEffect BlurRadius="16" ShadowDepth="8" Direction="-45" Color="Black" Opacity="0.6"/>
</Border.Effect>
<Grid>
<TextBlock Text="{TemplateBinding Content}" MaxWidth="400" TextWrapping="Wrap" Margin="3"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TooltipStyleForOtherStuffThanText" TargetType="ToolTip">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border BorderBrush="DimGray" BorderThickness="1" CornerRadius="5" Background="WhiteSmoke" Opacity="0.8"
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,10,0,-5" Width="Auto">
<Border.Effect>
<DropShadowEffect BlurRadius="16" ShadowDepth="8" Direction="-45" Color="Black" Opacity="0.6"/>
</Border.Effect>
<Grid>
<ContentPresenter Content="{TemplateBinding Content}" Margin="3"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
и тогда, когда мы используем TextBlock, назовем его стиль подсказки следующим образом:
<TextBlock Text="something">
<ToolTipService.ToolTip>
<ToolTip Style="{StaticResource TooltipStyleForText}">
<TextBlock Text="Some text"/>
</ToolTip>
</ToolTipService.ToolTip>
</TextBlock>
Это может быть не лучшим решением, потому что у нас есть два стиля, поэтому нам нужно указать написать несколько строк для простого TextBlock. Я надеюсь, что у кого-то есть лучшее решение.