locked
请问怎么在datagrid cell中显示tooltip呢? RRS feed

  • 问题

  • 请问怎么在datagrid cell中显示tooltip呢?
    我想使用behind code 来实现,不是使用xaml。

    谢谢
    2009年11月2日 17:44

答案

  • -----------------------------------------------------------

    好人做到底,给你一个完整的例子。

    仿造本例子,你可以实现任意外观的DataGrid。
    不仅可以做ToolTip,甚至是可以做成中国式的非常复杂的跨列表头的DataGrid(这个是我以前的心病,现在得到完美解决)

    事实上,只要你能用xaml能写的,基本都可以用
    XamlReader.Load在后台代码中动态生成。不光是什么ToolTip/Coverter之类简单的东西。

    -----------------------------------------------------------
    例子是用VB.NET做的,如果你用C#请做相应转换。
    我熟悉C#,VB.net,但一贯认为如果作为企业应用开发,VB.NET比C#好用多了。
    毕竟vb.net的版本已经是10.0了,比较成熟了;而C#才4.0,太年轻了。
    当然,大多数人是跟风用C#,不是两种语言都熟悉,如果他对两种都熟悉的话,他会选择VB.net。
    0)工程名称:SLDataGridTestSample

    1)MainPage.xaml

    <UserControl x:Class="SLDataGridTestSample.MainPage"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
                 xmlns:datap="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Data"
                 xmlns:my="clr-namespace:SLDataGridTestSample">
        <Grid x:Name="GrdRoot"
              Width="400"
              Height="200"
              Background="White">
            <data:DataGrid x:Name="DgrMain"
                           RowHeight="24"
                           ColumnHeaderHeight="40">
            </data:DataGrid>
        </Grid>
    </UserControl>

    2)MainPage.vb

    Partial Public Class MainPage
        Inherits UserControl

        Public Sub New()
            InitializeComponent()
        End Sub
        Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
            DgrMain.AutoGenerateColumns = False
            Call AddColumnWithTipAndConverter()

            Dim TestDataList As New List(Of CTestDataItem)
            TestDataList.Add(New CTestDataItem("UserId1", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId2", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId3", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId4", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId5", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId6", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId7", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId8", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId9", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId10", Rnd() * 100))
            DgrMain.ItemsSource = TestDataList
        End Sub
        Private Sub AddColumnWithTipAndConverter()
            Dim ColWithTipAndConverter As DataGridTemplateColumn = Nothing

            ColWithTipAndConverter = New DataGridTemplateColumn()
            ColWithTipAndConverter.Width = New DataGridLength(300)
            ColWithTipAndConverter.HeaderStyle = GetColumHeaderStyleWithTip("UserId", "UserId Header ToolTip")
            ColWithTipAndConverter.CellTemplate = GetColumnTemplateWithTipAndConverter("UserId")
            DgrMain.Columns.Add(ColWithTipAndConverter)

            ColWithTipAndConverter = New DataGridTemplateColumn()
            ColWithTipAndConverter.Width = New DataGridLength(200)
            ColWithTipAndConverter.HeaderStyle = GetColumHeaderStyleWithTip("UserScore", "UserScore Header ToolTip")
            ColWithTipAndConverter.CellTemplate = GetColumnTemplateWithTipAndConverter("UserScore")
            DgrMain.Columns.Add(ColWithTipAndConverter)
        End Sub
        Private Function GetColumHeaderStyleWithTip(ByVal HeaderStr As String, ByVal HeaderTip As String) As Style
            Dim Rlt As Style = Nothing
            Dim Xaml As String = "", StTmp As Setter = Nothing
            'SLDataGridTestSample --> YourNamespace, YourAssembly
            Xaml &= "<DataTemplate"
            Xaml &= "              xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"""
            Xaml &= "              xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"""
            Xaml &= "              xmlns:my=""clr-namespace:SLDataGridTestSample;assembly=SLDataGridTestSample"">" & vbCrLf
            Xaml &= "   <StackPanel>" & vbCrLf
            Xaml &= "      <TextBlock Text=""@HeaderStr"" ToolTipService.ToolTip=""@HeaderTip""></TextBlock>" & vbCrLf
            Xaml &= "   </StackPanel>" & vbCrLf
            Xaml &= "</DataTemplate>" & vbCrLf
            Xaml = Replace(Xaml, "@HeaderStr", HeaderStr, 1, -1, CompareMethod.Text)
            Xaml = Replace(Xaml, "@HeaderTip", HeaderTip, 1, -1, CompareMethod.Text)

            Rlt = New Style(GetType(System.Windows.Controls.Primitives.DataGridColumnHeader))

            StTmp = New Setter()
            StTmp.Property = System.Windows.Controls.Primitives.DataGridColumnHeader.ContentTemplateProperty
            StTmp.Value = CType(System.Windows.Markup.XamlReader.Load(Xaml), DataTemplate)
            Rlt.Setters.Add(StTmp)

            Return Rlt
        End Function
        Private Function GetColumnTemplateWithTipAndConverter(ByVal FieldName As String) As DataTemplate
            Dim Rlt As DataTemplate = Nothing
            Dim Xaml As String = "", Xaml1 As String = ""
            Xaml1 = "{Binding Path=@FieldName,ConverterParameter=@FieldName,Converter={StaticResource TestDataConverter},Mode=TwoWay}"
            Xaml1 = Replace(Xaml1, "@FieldName", FieldName, 1, -1, CompareMethod.Text)
            Xaml &= "<DataTemplate"
            Xaml &= "              xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"""
            Xaml &= "              xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"""
            Xaml &= "              xmlns:my=""clr-namespace:SLDataGridTestSample;assembly=SLDataGridTestSample"">" & vbCrLf
            Xaml &= "   <StackPanel>" & vbCrLf
            Xaml &= "      <StackPanel.Resources>" & vbCrLf
            Xaml &= "          <my:CTestDataConverter x:Key=""TestDataConverter""></my:CTestDataConverter>" & vbCrLf
            Xaml &= "      </StackPanel.Resources>" & vbCrLf
            Xaml &= "      <TextBlock VerticalAlignment=""Center"" Text=""@Xaml1"" ToolTipService.ToolTip=""@Xaml1""></TextBlock>" & vbCrLf
            Xaml &= "   </StackPanel>" & vbCrLf
            Xaml &= "</DataTemplate>" & vbCrLf
            Xaml = Replace(Xaml, "@Xaml1", Xaml1, 1, -1, CompareMethod.Text)
            Rlt = CType(System.Windows.Markup.XamlReader.Load(Xaml), DataTemplate)
            Return Rlt
        End Function
    End Class

    Public Class CTestDataItem
        Implements System.ComponentModel.INotifyPropertyChanged
        Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) _
        Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
        Private Sub NotifyPropertyChanged(ByVal PropertyName As String)
            RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(PropertyName))
        End Sub
        Dim _UserId As String
        Public Sub New()
            UserId = "" : UserScore = 0
        End Sub
        Public Sub New(ByVal TheUserId As String, ByVal TheUserScore As Double)
            UserId = TheUserId : UserScore = TheUserScore
        End Sub
        Public Property UserId() As String
            Get
                Return _UserId
            End Get
            Set(ByVal value As String)
                _UserId = value : NotifyPropertyChanged("UserId")
            End Set
        End Property
        Dim _UserScore As Double
        Public Property UserScore() As Double
            Get
                Return _UserScore
            End Get
            Set(ByVal value As Double)
                _UserScore = value : NotifyPropertyChanged("UserScore")
            End Set
        End Property
    End Class

    Public Class CTestDataConverter
        Implements System.Windows.Data.IValueConverter
        Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
            Dim Rlt As Object = value
            If value IsNot Nothing Then
                Select Case UCase(parameter & "")
                    Case UCase("UserScore") : Rlt = Format(CType(value, Double), "#0.00")
                End Select
            End If
            Return Rlt
        End Function
        Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
            Dim Rlt As Object = value
            Return Rlt
        End Function
    End Class

     

    2009年11月4日 4:52

全部回复

  • 通过在后台代码中创建
    Dim Xaml As String
    Xaml &="<DataTemplate>"
    Xaml &=     <TextBlock ToopTipService.ToolTip=""Your ToolTip"" />
    Xaml &="</DataTemplate>"
    Dim TplTipCell As DataTemplate = XamlReader.LoadXaml(XamlStr) '根据字符串生成对象的那个方法的名字记得不是很清除,你自己查一下
    YourDataGrid.Columns(???).CellTemplate = TplTipCell
    ..........................
    没写全,大致就是这样,具体你自己完成
    总之,完全没问题创建
    2009年11月2日 17:59
  • 如果我有类型转换函数,该如何调用呢?
    2009年11月3日 17:41
  • -----------------------------------------------------------

    好人做到底,给你一个完整的例子。

    仿造本例子,你可以实现任意外观的DataGrid。
    不仅可以做ToolTip,甚至是可以做成中国式的非常复杂的跨列表头的DataGrid(这个是我以前的心病,现在得到完美解决)

    事实上,只要你能用xaml能写的,基本都可以用
    XamlReader.Load在后台代码中动态生成。不光是什么ToolTip/Coverter之类简单的东西。

    -----------------------------------------------------------
    例子是用VB.NET做的,如果你用C#请做相应转换。
    我熟悉C#,VB.net,但一贯认为如果作为企业应用开发,VB.NET比C#好用多了。
    毕竟vb.net的版本已经是10.0了,比较成熟了;而C#才4.0,太年轻了。
    当然,大多数人是跟风用C#,不是两种语言都熟悉,如果他对两种都熟悉的话,他会选择VB.net。
    0)工程名称:SLDataGridTestSample

    1)MainPage.xaml

    <UserControl x:Class="SLDataGridTestSample.MainPage"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
                 xmlns:datap="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Data"
                 xmlns:my="clr-namespace:SLDataGridTestSample">
        <Grid x:Name="GrdRoot"
              Width="400"
              Height="200"
              Background="White">
            <data:DataGrid x:Name="DgrMain"
                           RowHeight="24"
                           ColumnHeaderHeight="40">
            </data:DataGrid>
        </Grid>
    </UserControl>

    2)MainPage.vb

    Partial Public Class MainPage
        Inherits UserControl

        Public Sub New()
            InitializeComponent()
        End Sub
        Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
            DgrMain.AutoGenerateColumns = False
            Call AddColumnWithTipAndConverter()

            Dim TestDataList As New List(Of CTestDataItem)
            TestDataList.Add(New CTestDataItem("UserId1", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId2", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId3", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId4", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId5", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId6", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId7", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId8", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId9", Rnd() * 100))
            TestDataList.Add(New CTestDataItem("UserId10", Rnd() * 100))
            DgrMain.ItemsSource = TestDataList
        End Sub
        Private Sub AddColumnWithTipAndConverter()
            Dim ColWithTipAndConverter As DataGridTemplateColumn = Nothing

            ColWithTipAndConverter = New DataGridTemplateColumn()
            ColWithTipAndConverter.Width = New DataGridLength(300)
            ColWithTipAndConverter.HeaderStyle = GetColumHeaderStyleWithTip("UserId", "UserId Header ToolTip")
            ColWithTipAndConverter.CellTemplate = GetColumnTemplateWithTipAndConverter("UserId")
            DgrMain.Columns.Add(ColWithTipAndConverter)

            ColWithTipAndConverter = New DataGridTemplateColumn()
            ColWithTipAndConverter.Width = New DataGridLength(200)
            ColWithTipAndConverter.HeaderStyle = GetColumHeaderStyleWithTip("UserScore", "UserScore Header ToolTip")
            ColWithTipAndConverter.CellTemplate = GetColumnTemplateWithTipAndConverter("UserScore")
            DgrMain.Columns.Add(ColWithTipAndConverter)
        End Sub
        Private Function GetColumHeaderStyleWithTip(ByVal HeaderStr As String, ByVal HeaderTip As String) As Style
            Dim Rlt As Style = Nothing
            Dim Xaml As String = "", StTmp As Setter = Nothing
            'SLDataGridTestSample --> YourNamespace, YourAssembly
            Xaml &= "<DataTemplate"
            Xaml &= "              xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"""
            Xaml &= "              xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"""
            Xaml &= "              xmlns:my=""clr-namespace:SLDataGridTestSample;assembly=SLDataGridTestSample"">" & vbCrLf
            Xaml &= "   <StackPanel>" & vbCrLf
            Xaml &= "      <TextBlock Text=""@HeaderStr"" ToolTipService.ToolTip=""@HeaderTip""></TextBlock>" & vbCrLf
            Xaml &= "   </StackPanel>" & vbCrLf
            Xaml &= "</DataTemplate>" & vbCrLf
            Xaml = Replace(Xaml, "@HeaderStr", HeaderStr, 1, -1, CompareMethod.Text)
            Xaml = Replace(Xaml, "@HeaderTip", HeaderTip, 1, -1, CompareMethod.Text)

            Rlt = New Style(GetType(System.Windows.Controls.Primitives.DataGridColumnHeader))

            StTmp = New Setter()
            StTmp.Property = System.Windows.Controls.Primitives.DataGridColumnHeader.ContentTemplateProperty
            StTmp.Value = CType(System.Windows.Markup.XamlReader.Load(Xaml), DataTemplate)
            Rlt.Setters.Add(StTmp)

            Return Rlt
        End Function
        Private Function GetColumnTemplateWithTipAndConverter(ByVal FieldName As String) As DataTemplate
            Dim Rlt As DataTemplate = Nothing
            Dim Xaml As String = "", Xaml1 As String = ""
            Xaml1 = "{Binding Path=@FieldName,ConverterParameter=@FieldName,Converter={StaticResource TestDataConverter},Mode=TwoWay}"
            Xaml1 = Replace(Xaml1, "@FieldName", FieldName, 1, -1, CompareMethod.Text)
            Xaml &= "<DataTemplate"
            Xaml &= "              xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"""
            Xaml &= "              xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"""
            Xaml &= "              xmlns:my=""clr-namespace:SLDataGridTestSample;assembly=SLDataGridTestSample"">" & vbCrLf
            Xaml &= "   <StackPanel>" & vbCrLf
            Xaml &= "      <StackPanel.Resources>" & vbCrLf
            Xaml &= "          <my:CTestDataConverter x:Key=""TestDataConverter""></my:CTestDataConverter>" & vbCrLf
            Xaml &= "      </StackPanel.Resources>" & vbCrLf
            Xaml &= "      <TextBlock VerticalAlignment=""Center"" Text=""@Xaml1"" ToolTipService.ToolTip=""@Xaml1""></TextBlock>" & vbCrLf
            Xaml &= "   </StackPanel>" & vbCrLf
            Xaml &= "</DataTemplate>" & vbCrLf
            Xaml = Replace(Xaml, "@Xaml1", Xaml1, 1, -1, CompareMethod.Text)
            Rlt = CType(System.Windows.Markup.XamlReader.Load(Xaml), DataTemplate)
            Return Rlt
        End Function
    End Class

    Public Class CTestDataItem
        Implements System.ComponentModel.INotifyPropertyChanged
        Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) _
        Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
        Private Sub NotifyPropertyChanged(ByVal PropertyName As String)
            RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(PropertyName))
        End Sub
        Dim _UserId As String
        Public Sub New()
            UserId = "" : UserScore = 0
        End Sub
        Public Sub New(ByVal TheUserId As String, ByVal TheUserScore As Double)
            UserId = TheUserId : UserScore = TheUserScore
        End Sub
        Public Property UserId() As String
            Get
                Return _UserId
            End Get
            Set(ByVal value As String)
                _UserId = value : NotifyPropertyChanged("UserId")
            End Set
        End Property
        Dim _UserScore As Double
        Public Property UserScore() As Double
            Get
                Return _UserScore
            End Get
            Set(ByVal value As Double)
                _UserScore = value : NotifyPropertyChanged("UserScore")
            End Set
        End Property
    End Class

    Public Class CTestDataConverter
        Implements System.Windows.Data.IValueConverter
        Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
            Dim Rlt As Object = value
            If value IsNot Nothing Then
                Select Case UCase(parameter & "")
                    Case UCase("UserScore") : Rlt = Format(CType(value, Double), "#0.00")
                End Select
            End If
            Return Rlt
        End Function
        Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
            Dim Rlt As Object = value
            Return Rlt
        End Function
    End Class

     

    2009年11月4日 4:52