Automatic tooltip when text is trimmed in DataGrid

2020-07-25 01:54发布

问题:

My application runs with C# and WPF (.net framework 4.0). My goal is to have a DataGrid in which the text in the cells is trimmed with an ellipsis, and automatically has a tooltip with the full text displayed only if the text in the cell is actually trimmed.

Solution 1: I'm currently using this to know if the text is trimmed or not: http://tranxcoder.wordpress.com/2008/10/12/customizing-lookful-wpf-controls-take-2/ The problem is that it only works when I resize the columns. The tooltips don't show up when the DataGrid is first loaded, when the columns are sorted, or when the ItemSource of the DataGrid is updated.

Solution 2: I've also tried this:http://www.scottlogic.com/blog/2011/01/31/automatically-showing-tooltips-on-a-trimmed-textblock-silverlight-wpf.html But the tooltips never appear on my DataGrid cells, while it works fine with isolated textblocks.

I'm looking for simple ways to improve Solution 1 and make it work in my DataGrid in all cases, or maybe a different approach.

The style for Solution 1:

<UserControl.Resources>
    <Style x:Key="TextColumnElementStyle" TargetType="TextBlock" BasedOn="{StaticResource TextBlockService}">
        <Style.Setters>
            <Setter Property="TextWrapping" Value="NoWrap" />
            <Setter Property="TextTrimming" Value="WordEllipsis" />
        </Style.Setters>
    </Style>
</UserControl.Resources>

The source code of the TextBlockService

The DataGrid for Solution 1:

<DataGrid ItemsSource="{Binding IssueList}" tbs:TextBlockService.AutomaticToolTipEnabled="True">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Description" Binding="{Binding Description}" 
            ElementStyle="{StaticResource TextColumnElementStyle}">
    </DataGrid.Columns>
</DataGrid>

Thanks

回答1:

I've found the perfect solution, based on an answer by xr280xr. It works out of the box, in any condition, and without using additional code.

The style, that I put in <DataGrid.Resources> :

<Style TargetType="{x:Type DataGridCell}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                <TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Text}" TextTrimming="CharacterEllipsis">
                    <TextBlock.ToolTip>
                        <ToolTip Visibility="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget, Converter={StaticResource TrimToVisConverter}}">
                            <ToolTip.Content>
                                <TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Text}"/>
                            </ToolTip.Content>
                        </ToolTip>
                    </TextBlock.ToolTip>
                 </TextBlock>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

The source of Converter={StaticResource TrimToVisConverter}:

public class TrimmedTextBlockVisibilityConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null) return Visibility.Collapsed;

        FrameworkElement textBlock = (FrameworkElement)value;

        textBlock.Measure(new System.Windows.Size(Double.PositiveInfinity, Double.PositiveInfinity));

        if (((FrameworkElement)value).ActualWidth < ((FrameworkElement)value).DesiredSize.Width)
            return Visibility.Visible;
        else
            return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}


回答2:

I can't comment yet, I lack points needed for it.

But I just want to add an extra tip to the accepted answer code, for noobs like me who want to use it.

If you want to link your Converter to its code, make sure to create a link in your Window/UserControl Resources as mentioned below:

<Window.Resources>
    <local:TrimmedTextBlockVisibilityConverter x:Key="TrimToVisConverter" />
</Window.Resources>

Additional thought on accepted answer: You also have to rewrite any style that comes with default DataGridCell template as DataGridCell States. Otherwise you lose clean view on row select and other stuff...