在 Silverlight DataGridTextColumn 上创建与绑定单元格内容不同的工具提示

发布于 2024-08-16 07:01:26 字数 1411 浏览 4 评论 0原文

我在 Silverlight 4 DataGrid 中有一个 DataGridTextColumn,我想在该列上设置一个与绑定值不同的工具提示值。

我知道我可以很轻松地使用模板化列来完成此操作 - 但它添加了大量额外的 XAML,并且使得阅读和维护变得很麻烦。

这可行,但有很多额外的代码 - 特别是如果需要更改模板

    <data:DataGridTemplateColumn Header="Name" Width="*">
        <data:DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <TextBlock TextTrimming="WordEllipsis" Text="{Binding FullName}"
                 ToolTipService.ToolTip="{Binding Email}" Width="Auto" Margin="5" />
            </DataTemplate>
        </data:DataGridTemplateColumn.CellTemplate>
    </data:DataGridTemplateColumn>

我想找到一种很好的方法来使用 Style 或继承的类来执行此操作。就像我说的,我的主要目标是以尽可能最好的方式减少 XAML 中像工具提示这样微不足道的东西的膨胀。

有一些类似的 stackoverflow 问题,其解决方案例如 this这个,但它们都显示与单元格内容相同的工具提示值(对于溢出时的实例)。虽然这通常是您想要的 - 我正在尝试向单元格的内容显示不同的工具提示。

我确实找到了一些继承类的示例代码(滚动到末尾),我尝试修改它,但由于我的 XAML 知识达不到标准而卡住了,而且我不想在这上面花上一整夜!这个特定的示例看起来似乎有效,但它看起来像是一种黑客攻击,我认为尝试修改它以使用两个依赖属性将是一个更大的黑客攻击。

附言。我希望编写良好的子类可以让我轻松绑定其他属性,例如 TextTrimming。

I have a DataGridTextColumn in a Silverlight 4 DataGrid and I want to set a ToolTip value on the column that is different from the bound value.

I know I can do this with a templated column quite easily - but it adds a huge amount of extra XAML and makes it cumbersome to read and maintain.

This works, but is a lot of extra code - especially if ever need to change the template

    <data:DataGridTemplateColumn Header="Name" Width="*">
        <data:DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <TextBlock TextTrimming="WordEllipsis" Text="{Binding FullName}"
                 ToolTipService.ToolTip="{Binding Email}" Width="Auto" Margin="5" />
            </DataTemplate>
        </data:DataGridTemplateColumn.CellTemplate>
    </data:DataGridTemplateColumn>

I'd like to find a nice way to do this with either a Style or inherited class. Like I said my main goal is to reduce bloat in the XAML for something so trivial as a tooltip in the best possible way.

There are a few similar stackoverflow questions with solutions like this and this, but they both show the same tooltip value as the contents of the cell (for instance when it overflows). While this is often what you want - I'm trying to show a different tooltip to the cell's contents.

I did find some sample code for an inherited class (scroll to end), which i tried to modify but got stuck becasue my XAML knowledge isn't up to par and I don't want to spend all night on this! This particular example appears like it works, but it looks like quite a hack and I think trying to modify it to work with two dependency properties is going to be an even bigger one.

PS. I would expect that a well written subclass would make it easy for me to bind other properties such as TextTrimming also.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

堇色安年 2024-08-23 07:01:26

尝试将此样式放入您的资源字典中:

<Style TargetType="{x:Type data:DataGridCell}">
    <Setter Property="ToolTip" Value="{Binding EMail}"/>
</Style>

要按照您在评论中的要求启用对任何属性的绑定,您需要发挥创意。我所做的是创建两个附加属性 ToolTipBindingIsToolTipBindingEnabled。在列上设置 ToolTipBinding 来确定工具提示,类似于确定单元格内容的 Binding 属性,而 IsToolTipBindingEnabled 为使用与我上面提到的类似的样式在 DataGridCell 对象上设置为 true

然后,我编写了代码,以便在加载单元格时,其父列的绑定将应用于其 ToolTip 属性。

下面是扩展类:

public class DGExtensions
{
    public static object GetToolTipBinding(DependencyObject obj)
    {
        return obj.GetValue(ToolTipBindingProperty);
    }

    public static void SetToolTipBinding(DependencyObject obj, object value)
    {
        obj.SetValue(ToolTipBindingProperty, value);
    }

    public static readonly DependencyProperty ToolTipBindingProperty =
        DependencyProperty.RegisterAttached(
            "ToolTipBinding",
            typeof(object),
            typeof(DGExtensions),
            new FrameworkPropertyMetadata(null));

    public static bool GetIsToolTipBindingEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsToolTipBindingEnabled);
    }

    public static void SetIsToolTipBindingEnabled(
        DependencyObject obj, 
        bool value)
    {
        obj.SetValue(IsToolTipBindingEnabled, value);
    }

    public static readonly DependencyProperty IsToolTipBindingEnabled =
        DependencyProperty.RegisterAttached(
            "IsToolTipBindingEnabled",
            typeof(bool),
            typeof(DGExtensions),
            new UIPropertyMetadata(false, OnIsToolTipBindingEnabledChanged));

    public static void OnIsToolTipBindingEnabledChanged(
        DependencyObject d, 
        DependencyPropertyChangedEventArgs e)
    {
        DataGridCell cell = d as DataGridCell;
        if (cell == null) return;

        bool nv = (bool)e.NewValue, ov = (bool)e.OldValue;

        // Act only on an actual change of property value.
        if (nv == ov) return; 

        if (nv)
            cell.Loaded += new RoutedEventHandler(cell_Loaded);
        else
            cell.Loaded -= cell_Loaded;
    }

    static void cell_Loaded(object sender, RoutedEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        if (cell == null) return;
        var binding = BindingOperations.GetBinding(
                        cell.Column, ToolTipBindingProperty);
        if (binding == null) return;

        cell.SetBinding(DataGridCell.ToolTipProperty, binding);

        // This only gets called once, so remove the strong reference.
        cell.Loaded -= cell_Loaded;
    }
}

XAML 用法示例:

<Window.Resources>
    <Style TargetType="{x:Type tk:DataGridCell}">
        <Setter 
            Property="dge:DGExtensions.IsToolTipBindingEnabled" 
            Value="True"/>
    </Style>
</Window.Resources>
<Grid>
    <tk:DataGrid ItemsSource="{Binding TheList}" AutoGenerateColumns="False">
        <tk:DataGrid.Columns>
            <tk:DataGridTextColumn 
                Header="PropA" 
                Binding="{Binding PropA}" 
                dge:DGExtensions.ToolTipBinding="{Binding PropB}"/>
            <tk:DataGridTextColumn 
                Header="PropB" 
                Binding="{Binding PropB}"/>
        </tk:DataGrid.Columns>
    </tk:DataGrid>
</Grid>

Try to put this style in your resource dictionary:

<Style TargetType="{x:Type data:DataGridCell}">
    <Setter Property="ToolTip" Value="{Binding EMail}"/>
</Style>

To enable binding to any property, as you requested in the comment, you need to get creative. What I did was create two attached properties ToolTipBinding and IsToolTipBindingEnabled. The ToolTipBinding is set on the column to determine the tooltip, similar to the Binding property that determines the content of the cell, and the IsToolTipBindingEnabled is set to true on the DataGridCell object using a style similar to the one I mentioned above.

Then, I wrote code so that when the cell is loaded, the binding from its parent column is applied to its ToolTip property.

Here's the extension class:

public class DGExtensions
{
    public static object GetToolTipBinding(DependencyObject obj)
    {
        return obj.GetValue(ToolTipBindingProperty);
    }

    public static void SetToolTipBinding(DependencyObject obj, object value)
    {
        obj.SetValue(ToolTipBindingProperty, value);
    }

    public static readonly DependencyProperty ToolTipBindingProperty =
        DependencyProperty.RegisterAttached(
            "ToolTipBinding",
            typeof(object),
            typeof(DGExtensions),
            new FrameworkPropertyMetadata(null));

    public static bool GetIsToolTipBindingEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsToolTipBindingEnabled);
    }

    public static void SetIsToolTipBindingEnabled(
        DependencyObject obj, 
        bool value)
    {
        obj.SetValue(IsToolTipBindingEnabled, value);
    }

    public static readonly DependencyProperty IsToolTipBindingEnabled =
        DependencyProperty.RegisterAttached(
            "IsToolTipBindingEnabled",
            typeof(bool),
            typeof(DGExtensions),
            new UIPropertyMetadata(false, OnIsToolTipBindingEnabledChanged));

    public static void OnIsToolTipBindingEnabledChanged(
        DependencyObject d, 
        DependencyPropertyChangedEventArgs e)
    {
        DataGridCell cell = d as DataGridCell;
        if (cell == null) return;

        bool nv = (bool)e.NewValue, ov = (bool)e.OldValue;

        // Act only on an actual change of property value.
        if (nv == ov) return; 

        if (nv)
            cell.Loaded += new RoutedEventHandler(cell_Loaded);
        else
            cell.Loaded -= cell_Loaded;
    }

    static void cell_Loaded(object sender, RoutedEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        if (cell == null) return;
        var binding = BindingOperations.GetBinding(
                        cell.Column, ToolTipBindingProperty);
        if (binding == null) return;

        cell.SetBinding(DataGridCell.ToolTipProperty, binding);

        // This only gets called once, so remove the strong reference.
        cell.Loaded -= cell_Loaded;
    }
}

Example XAML usage:

<Window.Resources>
    <Style TargetType="{x:Type tk:DataGridCell}">
        <Setter 
            Property="dge:DGExtensions.IsToolTipBindingEnabled" 
            Value="True"/>
    </Style>
</Window.Resources>
<Grid>
    <tk:DataGrid ItemsSource="{Binding TheList}" AutoGenerateColumns="False">
        <tk:DataGrid.Columns>
            <tk:DataGridTextColumn 
                Header="PropA" 
                Binding="{Binding PropA}" 
                dge:DGExtensions.ToolTipBinding="{Binding PropB}"/>
            <tk:DataGridTextColumn 
                Header="PropB" 
                Binding="{Binding PropB}"/>
        </tk:DataGrid.Columns>
    </tk:DataGrid>
</Grid>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文