我试图将一些值绑定到ToolTipService.ShowDuration
和CellStyle
的DataGridTextColumn
中的一些其他ToolTip属性。
通常,我正在做这样的事情:
<UserControl
...namespace declarations...>
<UserControl.Resources>
<mycontrols:BindingProxy x:Key="proxy" Data="{Binding MySettings}"/>
</UserControl.Resources>
<DataGrid>
<DataGridTextColumn
Binding="{Binding SomeBinding}">
<DataGridTextColumn.CellStyle>
<Style
TargetType="DataGridCell"
BasedOn="{StaticResource ResourceKey={x:Type DataGridCell}}">
<Setter
Property="ToolTipService.ShowDuration"
Value="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"/>
<Setter Property="ToolTip">
<Setter.Value>
<TextBlock
Text="{Binding SomeBinding}"
MaxWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}"
TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
</DataGrid>
</UserControl>
由于ToolTip有自己的可视化树,我使用这样的绑定代理:
public class BindingProxy : Freezable
{
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}
到目前为止,所有工作都按预期进行。但是我想重新使用这个DataGridTextColumn,所以我创建了这样的新文件:
<DataGridTextColumn
x:Class="Test.MyControls.DataGridLargeTextColumn"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test.MyControls">
<DataGridTextColumn.CellStyle>
<Style
TargetType="DataGridCell"
BasedOn="{StaticResource ResourceKey={x:Type DataGridCell}}">
<Setter
Property="ToolTipService.ShowDuration"
Value="{Binding ToolTipDuration}"/>
<Setter Property="ToolTip">
<Setter.Value>
<TextBlock
Text="{Binding SomeBinding}"
MaxWidth="{Binding ToolTipWidth}"
TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
代码背后:
public partial class DataGridLargeTextColumn : DataGridTextColumn
{
public int ToolTipDuration
{
get { return (int)GetValue(ToolTipDurationProperty); }
set { SetValue(ToolTipDurationProperty, value); }
}
public static readonly DependencyProperty ToolTipDurationProperty =
DependencyProperty.Register("ToolTipDuration", typeof(int), typeof(DataGridLargeTextColumn), new UIPropertyMetadata(default(int)));
public string SomeBinding
{
get { return (string)GetValue(SomeBindingProperty); }
set { SetValue(SomeBindingProperty, value); }
}
public static readonly DependencyProperty SomeBindingProperty =
DependencyProperty.Register("SomeBinding", typeof(string), typeof(DataGridLargeTextColumn), new UIPropertyMetadata(default(string)));
public int ToolTipWidth
{
get { return (int)GetValue(ToolTipWidthProperty); }
set { SetValue(ToolTipWidthProperty, value); }
}
public static readonly DependencyProperty ToolTipWidthProperty =
DependencyProperty.Register("ToolTipWidth", typeof(int), typeof(DataGridLargeTextColumn), new UIPropertyMetadata(default(int)));
public DataGridLargeTextColumn()
{
InitializeComponent();
}
}
这不起作用,因为ToolTip有它自己的可视树,但由于我无处可放代理,我不知道如何使其工作或甚至可能。我找到了this answer,它似乎在正确的轨道上,然而,我试图像这样实现它,没有运气:
<Setter
Property="ToolTipService.ShowDuration"
Value="{Binding Path=PlacementTarget.(local:DataGridLargeTextColumn.ToolTipDuration), RelativeSource={RelativeSource Self}}"/>
<Setter Property="ToolTip">
<Setter.Value>
<TextBlock
Text="{Binding Path=PlacementTarget.(local:DataGridLargeTextColumn.SomeBinding), RelativeSource={RelativeSource Self}}"
MaxWidth="{Binding Path=PlacementTarget.(local:DataGridLargeTextColumn.ToolTipWidth), RelativeSource={RelativeSource Self}}"
TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
</Setter.Value>
</Setter>
我使用PlacementTarget错了吗?如果没有,为什么它不起作用,还有另一种解决方案吗?
更新:
根据马克的回答,我修改了DataGridLargeTextColumn
的风格:
<Style
TargetType="DataGridCell"
BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter
Property="ToolTipService.ShowDuration" Value="{Binding Path=PlacementTarget.ToolTipShowDuration, RelativeSource={x:Static RelativeSource.Self}}"/>
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}">
<TextBlock
Text="{Binding DataContext.SomeBinding}"
MaxWidth="{Binding Column.ToolTipWidth}"
TextWrapping="Wrap" TextTrimming="CharacterEllipsis"/>
</ToolTip>
</Setter.Value>
</Setter>
</Style>
而我正在使用这样的控件:
<UserControl
...namespace declarations...>
<UserControl.Resources>
<mycontrols:BindingProxy x:Key="proxy" Data="{Binding MySettings}"/>
</UserControl.Resources>
<DataGrid>
<DataGrid.Columns>
<mycontrols:DataGridLargeTextColumn
Binding="{Binding SomeBinding}"
ToolTipShowDuration="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"
ToolTipWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}"/>
</DataGrid.Columns>
</DataGrid>
</UserControl>
宽度绑定现在就像魅力一样,但有两个问题我仍然无法解决:
Text
属性设置为SomeBinding
,在这种特殊情况下可以,但是我希望能够将它设置为任何东西,所以我尝试使用上面的DependencProperty
声明它,如下所示:Text="{Binding Column.ToolTipText}"
如果我使用字符串文字,这可以正常工作:
<myControls:DataGridLargeTextColumn
Binding="{Binding SomeBinding}"
ToolTipText="12345"
ToolTipShowDuration="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"
ToolTipWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}"/>
但是当我尝试绑定它时它不起作用,这正是我想要实现的:
<myControls:DataGridLargeTextColumn
Binding="{Binding SomeBinding}"
ToolTipText="{Binding SomeOtherPropertyBinding}"
ToolTipShowDuration="{Binding Data.ToolTipDuration, Source={StaticResource proxy}}"
ToolTipWidth="{Binding Data.ToolTipMaxWidth, Source={StaticResource proxy}}"/>
默认情况下,ToolTip的DataContext设置为单元格的DataContext。但是,您正在尝试绑定到单元格列中的依赖项属性,因此您将不得不将DataContext更改为指向单元格本身,然后在您要访问数据时明确引用DataContext
,当您访问Column
时想要访问DataGridLargeTextColumn中的DP。
换句话说,除了内容之外,还要显式声明ToolTip并设置其DataContext,如下所示:
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}">
<TextBlock
Text="{Binding DataContext.SomeBinding}"
Width="{Binding Column.ToolTipWidth}" />
</ToolTip>
</Setter.Value>
</Setter>
...在这种情况下,Text
绑定到数据,Width
绑定到自定义列DP。
或者你也可以按原样保留DataContext,而是使用ToolTip的Tag
属性作为DataGridLargeTextColumn的绑定代理:
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip Tag="{Binding Path=PlacementTarget.Column, RelativeSource={x:Static RelativeSource.Self}}">
<TextBlock
Text="{Binding SomeBinding}"
Width="{Binding Tag.ToolTipWidth, RelativeSource={RelativeSource AncestorType=ToolTip}}" />
</ToolTip>
</Setter.Value>
</Setter>