以编程方式定义的WPF GridViewColumnHeader上的定义Click事件

时间:2019-02-22 12:49:17

标签: wpf vb.net

我正在以编程方式在WPF中创建GridViewColumn,如下所示:

Dim oGVCol As GridViewColumn = New GridViewColumn

Dim oHeaderTemplate As DataTemplate
oHeaderTemplate = New DataTemplate

Dim oGridFactory As FrameworkElementFactory = New FrameworkElementFactory(GetType(Grid))
oHeaderTemplate.VisualTree = oGridFactory

oGridFactory.SetValue(Grid.BackgroundProperty, Brushes.Transparent)

oGVCol.HeaderTemplate = oHeaderTemplate

(我已删除了无关的代码来设置网格的内容)

我不知道是如何为GridViewColumnHeader本身添加一个“ click”事件。我可以将事件添加到Grid以及通过Factory对象添加的任何其他控件,没问题。但是我对如何在标头本身中添加事件感到困惑。

如果您在VB.NET中有解决方案,那很好,但是C#也可以。

一次(失败)尝试:

AddHandler TryCast(oGVCol.Header, GridViewColumnHeader).Click, AddressOf HeaderClick

可悲的是,事实证明我无法将oGVCol.Header强制转换为GridViewColumnHeader。

1 个答案:

答案 0 :(得分:0)

好吧,可能看起来不太好,但是我找到了解决这个问题的不错的方法。

首先,当我为标题的可视树中的根元素创建Grid Factory时,给它起一个名字

oGridFactory.SetValue(Grid.NameProperty, <column name here>))

(请注意,名称中只能包含字母,数字和下划线,因此,如果您的数据中包含不包含这些名称的列名称,则需要在此处进行处理,以将无效名称转换为有效名称,以及下面的内容,以便在必要时将其恢复为原始名称。...在此我不会详细说明该功能)

此外,我将事件处理程序添加到模板中列标题的“根”网格中:

oGridFactory.AddHandler(Grid.SizeChangedEvent,
                        New SizeChangedEventHandler(AddressOf ColumnHeaderSizeChanged))

“魔术”发生在过程ColumnHeaderSizeChanged中。首次渲染网格时,以及用户手动调整列大小时,都将调用此过程。

签名:

Private Sub ColumnHeaderSizeChanged(sender As Object, e As SizeChangedEventArgs)

我保留一个List(Of GridViewColumnHeaders),当我需要用另一个替换Grid时将其重置为一个空列表。然后,在ColumnHeaderSizeChanged事件中,执行以下操作:

我们要做的第一件事是进入“列标题”中控件的“根”。例如,您的列标题可能包含一个TextBlock来显示列名,以及一个图标来表明它已被向上或向下排序。诸如此类的事情。当用户单击标题时,他们可能会单击这些控件中的任何一个,因此:

    Dim oParent As Object
    Dim oColHeader As GridViewColumnHeader = Nothing
    Dim sColHeaderName As String = String.Empty
    Dim oGWH As Grid = Nothing

    oParent = e.OriginalSource 'This may be any of the controls in the header.
    If Not oParent Is Nothing Then
        Try
            While Not oParent.Parent Is Nothing
                'So we keep going down the Tree until we hit the Root Parent
                'which will be the main Grid created in the Grid Factory
                oParent = oParent.Parent
            End While
        Catch

        End Try
    End If

    'But at this point, if we still have a control, it will be the main Grid
    If oParent Is Nothing Then
        Exit Sub
    End If
    If TryCast(oParent, Grid) Is Nothing Then
        'what the heck is this? This SHOULD be the Grid at the root of the Visual Tree,
        'so if, for whatever reason, this is NOT a Grid, get outta here.
        Exit Sub
    End If

到目前为止,我们位于主Grid上,但是现在我们需要获取已在其中创建此Grid的GridViewColumnHeader。所以现在我们去TemplatedParent

        While Not oParent.TemplatedParent Is Nothing
            oParent = oParent.TemplatedParent
            oColHeader = TryCast(oParent, GridViewColumnHeader)
            If Not oColHeader Is Nothing Then
                'This procedure is called both when the Grid View is first rendered,
                'and when the user is dragging the column width.
                If Mouse.LeftButton = MouseButtonState.Pressed Then
                    'Do something appropriate to when the user is resizing the column
                Else
                    'Do something appropriate to when the grid
                    'is first Rendered or re-displayed
                End If
                Exit While
            End If
        End While

这时,我们有了所需的GridViewColumnHeader,因此可以将其添加到List并为其Click事件添加一个Handler。 moColHeaders是List(Of GridViewColumnHeaders)

    If Not oColHeader Is Nothing Then
        If Not moColHeaders.Contains(oColHeader) Then
            oColHeader.Name = <column name here>
            moColHeaders.Add(oColHeader) 'Only need to add it once!
            AddHandler oColHeader.Click, AddressOf HeaderClick
        End If
    End If

现在,您可以编码HeaderClick过程以处理GridViewColumnHeader.Click事件。

签名:

Private Sub HeaderClick(sender As Object, e As RoutedEventArgs)