Стиль всплывающей подсказки в 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. Я надеюсь, что у кого-то есть лучшее решение.

Другие вопросы по тегам