Хитрость в ToolTip
s заключается в том, что ToolTip
- это объект, который вы связываете с элементом управления, а не часть визуального дерева элемента управления. Таким образом, вы не можете заполнить его так, как вы бы заполнили элементы в визуальном дереве, например ::100100
<TextBox.ToolTip>
<StackPanel>
...put bound controls here
</StackPanel>
</TextBox.ToolTip>
Вместо этого вам нужно создать конкретный экземпляр всплывающей подсказки и назначить ему стиль, который устанавливает DataContext
(очень важно; именно так вы можете привязать свойства источника данных к его «размещению» target, "т.е. элемент управления, отображающий всплывающую подсказку) и его Template
. Затем поместите визуальное дерево ToolTip
, включая привязки, в шаблон. Наконец, ссылка на ToolTip
в вашем контроле.
Итак, вот TextBox
, чья Binding
выполняет проверку:
<TextBox ToolTip="{StaticResource ErrorToolTip}">
<TextBox.Text>
<Binding Source="SourceProperty">
<Binding.ValidationRules>
<DataErrorValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Использует это ToolTip
:
<ToolTip x:Key="ErrorToolTip" Style="{StaticResource ErrorToolTipStyle}"/>
И ToolTip
использует этот стиль, который получает свое содержимое из свойства ValidationError
источника привязки TextBox
:
<Style x:Key="ErrorToolTipStyle" TargetType="{x:Type ToolTip}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="HasDropShadow" Value="True"/>
<Setter Property="DataContext" Value="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border
Name="Border"
BorderThickness="1"
BorderBrush="LightGray">
<StackPanel Orientation="Vertical">
<Label Background="Firebrick" Foreground="White" FontWeight="Bold" Margin="4">Validation error</Label>
<TextBlock Margin="10" Text="{Binding ValidationError}"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="HasDropShadow" Value="true">
<Setter TargetName="Border" Property="CornerRadius" Value="4"/>
<Setter TargetName="Border" Property="SnapsToDevicePixels" Value="true"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Я не уверен в этом, но я думаю, что единственная часть вышеперечисленного, которая фактически должна быть установлена в стиле, это DataTrigger
, устанавливающая DataContext
; Я думаю, что большинство всего остального можно просто явно указать в визуальном дереве ToolTip
. Но я, наверное, не думаю о чем-то важном.