【问题标题】:How do I find the image in a WPF Datagrid ColumnHeader so I can change the image?如何在 WPF Datagrid ColumnHeader 中找到图像以便更改图像?
【发布时间】:2016-01-14 04:03:08
【问题描述】:

我正在尝试实现类似 Excel 的列过滤和排序。为此,我使用了 DataTemplate 来定义列标题。

    <DataGrid x:Name="dataGrid" HorizontalAlignment="Stretch"  VerticalAlignment="Stretch" CanUserSortColumns="False">
        <DataGrid.Resources>
            <Style TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="ContentTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="23"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <Button x:Name="ExcelFilterButton" Tag="{Binding}" Click="ExcelFilterButton_Click" Margin="0,0,0,0" BorderThickness="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Focusable="False" Grid.Column="0">
                                    <Image Source="Resources\NoSortNoFilter.png" Width="19" Height="19" />
                                </Button>
                                <TextBlock Text="{Binding}" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" />
                            </Grid>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.Resources>
    </DataGrid>

它出来了nicely

我尝试使用 VisualTreeHelper 从 Column Header 中查找图像,但 Header 属性是一个字符串。我也尝试过使用 HeaderStyle 和 HeaderTemplate 属性,但无济于事。

使用名为 Snoop 的 WPF Spy 程序,我可以在其中看到 image,但仍然无法弄清楚如何在代码中访问它。我需要在代码中访问它的原因是根据该列是否已排序和/或过滤来更改图像。 (这可以在 XAML 中完成吗?)

【问题讨论】:

    标签: wpf wpfdatagrid datacolumn visual-tree


    【解决方案1】:

    好的,我想出了怎么做。这很可能不是正确的方法,但我找到了一种可行的方法。

    给你一些关于这个过程的信息。

    1. 用户单击标题按钮。按钮标签属性绑定到列标题。
    2. click 事件处理程序实例化上下文菜单并将其 Tag 设置为与按钮 Tag 相同。
    3. 用户单击菜单项。
    4. 事件处理程序将上下文菜单标记属性和图像名称发送到查找按钮的例程,然后是按钮中的图像,并更改图像。

    现在是代码。

    按钮点击事件处理程序:

        Private Sub ExcelFilterButton_Click(sender As Object, e As RoutedEventArgs)
            With DirectCast(Resources("sortContextMenu"), ContextMenu)
                .Tag = DirectCast(sender, Button).Tag
                .IsOpen = True
            End With
        End Sub
    

    菜单项点击事件处理程序

    Private Sub ContextMenuItem_Click(Sender As Object, e As RoutedEventArgs)
        If TypeOf Sender Is MenuItem Then
            'just testing, of course this isn't all this handler does.
            SetColumnSortImage(Sender.Tag, "Filtered")
        End If
    End Sub
    

    SetColumnSortImage 例程,它调用以下两个例程。

    Private Sub SetColumnSortImage(Tag As String, ImageName As String)
        Dim btn As Button = Nothing
        GetSortButton(Of Button)(dataGrid, Tag, btn)
        If btn IsNot Nothing Then
            Dim img As Image = GetChildOfType(Of Image)(btn)
            img.Source = New BitmapImage(New Uri("pack://application:,,,/Resources/" & ImageName & ".png"))
        End If
    End Sub
    

    GetSortButton 例程

    Private Sub GetSortButton(Of T As DependencyObject)(dep As DependencyObject, Tag As String, ByRef out As DependencyObject)
        If dep IsNot Nothing Then
            If TypeOf dep Is Button AndAlso CType(dep, Button).Tag = Tag Then
                out = dep
            Else
                If VisualTreeHelper.GetChildrenCount(dep) > 0 Then
                    For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(dep) - 1
                        GetSortButton(Of T)(VisualTreeHelper.GetChild(dep, i), Tag, out)
                    Next
                End If
            End If
        End If
    End Sub
    

    这个例程在 C# 的 StackOverflow 上的其他地方找到。我把它转成VB了。

    Private Function GetChildOfType(Of T As DependencyObject)(depObj As DependencyObject) As T
        If depObj Is Nothing Then
            Return Nothing
        End If
    
        For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(depObj) - 1
            Dim child = VisualTreeHelper.GetChild(depObj, i)
    
            Dim result = If(TryCast(child, T), GetChildOfType(Of T)(child))
            If result IsNot Nothing Then
                Return result
            End If
        Next
        Return Nothing
    End Function
    

    你可能有更好的方法。有的话请发帖。

    【讨论】:

      猜你喜欢
      • 2013-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-19
      相关资源
      最近更新 更多