如何在 WPF DataGrid 的展开控件右上角添加按钮

3

我想知道如何将按钮放在我的展开器的右侧,这是当我的展开器折叠时的样子(无论是否展开,我都需要按钮)。

enter image description here

我需要实现这个功能,当用户点击按钮时,我必须获取订单ID并执行某些操作! enter image description here

以下是我的代码:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="10*" />
    </Grid.ColumnDefinitions>

    <DataGrid IsSynchronizedWithCurrentItem="False" Grid.Column="0" VerticalGridLinesBrush="Transparent"  RowHeaderWidth="0" CanUserAddRows="False" AutoGenerateColumns="False"  x:Name="datagrid1" Margin="10,150,8,50" Background="Transparent" RowBackground="#FF494949"  VerticalContentAlignment="Center" HorizontalContentAlignment="Center" ItemsSource="{Binding}">
        <DataGrid.Resources>
            <Style TargetType="{x:Type DataGridColumnHeader}">
                <Setter Property="Background" Value="Black"/>
                <Setter Property="Opacity" Value="0.5"/>
                <Setter Property="Foreground" Value="White"/>
                <Setter Property="HorizontalContentAlignment" Value="Center" />
                <Setter Property="FontSize" Value="15"/>
                <Setter Property="FontFamily" Value="Arial"/>
                <Setter Property="Height" Value="50"/>
            </Style>


    <Style x:Key="TextInCellCenter" TargetType="{x:Type TextBlock}" >
        <Setter Property="TextAlignment" Value="Center"/>
    </Style>

    <Style TargetType="{x:Type TextBlock}" x:Key="RightAligElementStyle">
        <Setter Property="TextAlignment" Value="Right"/>
    </Style>

    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#83D744"/>

    </DataGrid.Resources>

        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Title}"       Header="Product Name"   Width="0.25*"   Foreground="White" FontSize="20"  FontFamily="Verdana" />
            <DataGridTextColumn Binding="{Binding Quantity}"    ElementStyle="{StaticResource TextInCellCenter}"     Header="Quantity"    Foreground="White"     Width="0.15*"       FontSize="20" FontFamily="Verdana" />
            <DataGridTextColumn Binding="{Binding User}"        ElementStyle="{StaticResource TextInCellCenter}"     Header="User"        Foreground="White"     Width="0.20*"       FontSize="20" FontFamily="Verdana" />
        </DataGrid.Columns>

    <DataGrid.GroupStyle>
        <!-- Style for groups at top level. -->
        <GroupStyle>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                <Expander IsExpanded="True"  Background="#83D744">
                                    <Expander.Header>
                                        <DockPanel Height="50">
                                            <TextBlock FontWeight="Bold" FontSize="20" Height="25"  Foreground="Black" Text="{Binding Path=Name,StringFormat= OrderNumber:# {0}}" />
                                        </DockPanel>
                                    </Expander.Header>
                                    <Expander.Content>
                                        <ItemsPresenter />
                                    </Expander.Content>
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </DataGrid.GroupStyle>
</DataGrid>

感谢大家,

谢谢。

在Joe的回答下,我实现了这个,但是为什么DataGrid中的最后一项没有按钮呢?请看这张截图:

enter image description here

代码如下:

<Grid>
<Grid.ColumnDefinitions>
    <ColumnDefinition Width="10*" />
</Grid.ColumnDefinitions>

<DataGrid IsSynchronizedWithCurrentItem="False" Grid.Column="0" VerticalGridLinesBrush="Transparent"  RowHeaderWidth="0" CanUserAddRows="False" AutoGenerateColumns="False"  x:Name="datagrid1" Margin="10,150,8,50" Background="Transparent" RowBackground="#FF494949"  VerticalContentAlignment="Center" HorizontalContentAlignment="Center" ItemsSource="{Binding}">
    <DataGrid.Resources>
        <Style TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="Background" Value="Black"/>
            <Setter Property="Opacity" Value="0.5"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="FontSize" Value="15"/>
            <Setter Property="FontFamily" Value="Arial"/>
            <Setter Property="Height" Value="50"/>
        </Style>


<Style x:Key="TextInCellCenter" TargetType="{x:Type TextBlock}" >
    <Setter Property="TextAlignment" Value="Center"/>
</Style>

<Style TargetType="{x:Type TextBlock}" x:Key="RightAligElementStyle">
    <Setter Property="TextAlignment" Value="Right"/>
</Style>

<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#83D744"/>

</DataGrid.Resources>

    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Title}"       Header="Product Name"   Width="0.25*"   Foreground="White" FontSize="20"  FontFamily="Verdana" />
        <DataGridTextColumn Binding="{Binding Quantity}"    ElementStyle="{StaticResource TextInCellCenter}"     Header="Quantity"    Foreground="White"     Width="0.15*"       FontSize="20" FontFamily="Verdana" />
        <DataGridTextColumn Binding="{Binding User}"        ElementStyle="{StaticResource TextInCellCenter}"     Header="User"        Foreground="White"     Width="0.20*"       FontSize="20" FontFamily="Verdana" />
    </DataGrid.Columns>



    <DataGrid.GroupStyle>
        <!-- Style for groups at top level. -->
        <GroupStyle>
            <GroupStyle.ContainerStyle>
                <Style TargetType="{x:Type GroupItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type GroupItem}">
                                <Expander IsExpanded="True"  Background="Black" Opacity="0.7">
                                    <Expander.Header>
                                        <DockPanel Height="50" Width="{Binding
                                                          RelativeSource={RelativeSource
                                                          Mode=FindAncestor,
                                                          AncestorType={x:Type Expander}},
                                                          Path=ActualWidth}">
                                            <Button DockPanel.Dock="Right" Content="Test Button" Margin="0,0,28,0"/>
                                            <TextBlock FontWeight="Normal" FontFamily="Verdana" FontSize="20" Height="25" Foreground="#83D744" Text="{Binding Path=Name,StringFormat= Order Number:# {0}}" />
                                        </DockPanel>
                                    </Expander.Header>
                                    <Expander.Content>
                                        <ItemsPresenter />
                                    </Expander.Content>
                                </Expander>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </GroupStyle.ContainerStyle>
        </GroupStyle>
    </DataGrid.GroupStyle>
</DataGrid>

所以由于某些奇怪的原因,最后一个项目上的按钮不可见...

1
你已经在添加自定义的TextBlock作为标题了,只需在<Expander.Header> Dock面板中添加按钮即可。 - Joe
是的,但如何将它移动到Expander.Header的右上角? - Roxy'Pro
它在一个停靠面板中,使用 DockPanel.Dock="Right"。 - Joe
你能发一点更多的代码吗?我尝试过了,但按钮没有移动到右边。 - Roxy'Pro
2个回答

7
啊,我之前遇到过这个问题。如果你选择DockPanel组件,你可以很快看到问题所在,容纳标题内容的容器被对齐到了“左侧”,而不是“拉伸”,因此将停靠面板对齐到右侧并不能得到你想要的结果:enter image description here由于停靠面板本身被固定在“左侧”对齐方式,即使我们将其设置为“拉伸”,也无济于事。
一种解决方法是使用一些绑定来设置它的宽度:
   <Expander.Header>
        <DockPanel Height="50" Width="{Binding
                                RelativeSource={RelativeSource
                                  Mode=FindAncestor,
                                  AncestorType={x:Type Expander}},
                                Path=ActualWidth}">
            <Button DockPanel.Dock="Right" Content="Test" Margin="0,0,28,0"/>
            <TextBlock FontWeight="Bold" FontSize="20" Height="25"  Foreground="Black" Text="Heading" />
        </DockPanel>
    </Expander.Header>

导致结果为:

enter image description here

然而这并不理想。请注意,我不得不使用Padding="0,0,28,0"填充按钮的右侧,否则它会被推出屏幕。

更好的解决方案是为扩展器创建自己的样式。

编辑。考虑到您所面临的问题(非常奇怪),我认为最好的解决方案是重新设计扩展器,以便使用网格正确地结构化。以下是一个例子:

<Expander.Template>
    <ControlTemplate TargetType="Expander">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Name="ContentRow" Height="0"/>
            </Grid.RowDefinitions>

            <Border Background="Green">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>

                    <ToggleButton IsChecked="{Binding Path=IsExpanded,Mode=TwoWay,
                                    RelativeSource={RelativeSource TemplatedParent}}">
                        <ToggleButton.Template>
                            <ControlTemplate TargetType="ToggleButton">
                                <Border Padding="6,4" Background="Transparent">
                                    <Path Name="Arrow"
                                            Fill="Black"
                                            HorizontalAlignment="Center"
                                            VerticalAlignment="Center"
                                            Data="M 0 0 L 8 8 L 16 0 Z"/>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="ToggleButton.IsMouseOver" Value="true">
                                        <Setter TargetName="Arrow" Property="Fill"
                                                Value="LightGreen" />
                                    </Trigger>
                                    <Trigger Property="IsPressed" Value="true">
                                        <Setter TargetName="Arrow" Property="Fill"
                                                Value="DarkGreen" />
                                    </Trigger>
                                    <Trigger Property="IsChecked" Value="true">
                                        <Setter TargetName="Arrow" Property="Data"
                                                Value="M 0 8 L 8 0 L 16 8 Z" />
                                    </Trigger>
                                    <Trigger Property="IsEnabled" Value="False">
                                        <Setter TargetName="Arrow" Property="Opacity"
                                                Value="0.5" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </ToggleButton.Template>
                    </ToggleButton>
                    <ContentPresenter Grid.Column="1"
                                        Margin="4" 
                                        ContentSource="Header" 
                                        RecognizesAccessKey="True" />
                </Grid>
            </Border>
            <ContentPresenter Grid.Row="1"/>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="IsExpanded" Value="True">
                <Setter TargetName="ContentRow" Property="Height"
                        Value="{Binding ElementName=Content,Path=DesiredHeight}" />
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
</Expander.Template>

这意味着您必须更改其外观(但看起来您想要这样做)。如果您注意到,头部ContentPresenter在网格中,因此会将Expander的整个长度拉伸。我还需要制作一个自定义的切换按钮。

这是结果:

enter image description here


一切都很清楚,伙计,我没有完全理解宽度部分,但我会尝试弄清楚。 - Roxy'Pro
老铁,为什么我在DataGrid的最后一个项目上看不到按钮啊?我给你发了屏幕截图,请查看我发布的帖子的编辑。 - Roxy'Pro
垂直滑块是否出现,只是您无法单击它,还是根本不出现? - Joe
它出现了,但它不起作用,我无法使用它向上和向下滚动,还有我意识到的是:当我将其设置为我的DockPanel的宽度时,我可以将按钮向右移动并使用垂直滑块,但某种方式会破坏我的主窗口,所以我必须向右滚动大约20像素才能看到我的按钮Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=ActualWidth}",我可以使用右边距将我的按钮移动到屏幕内部,但仍然会破坏我的主窗口,因此我可以使用水平滑块左右滚动,因为屏幕已经损坏:( - Roxy'Pro
1
添加了更好的解决方案。 - Joe
显示剩余8条评论

0
定义一个按钮的数据模板:
  <Window.Resources>
    <DataTemplate x:Key="DataTemplateButton">
        <Button Width="100" Height="30" Content="Button"/>
    </DataTemplate>
</Window.Resources>

设置 Expander 的 HeaderTemplate:

  <Expander  IsExpanded="true" Grid.Column="0" HeaderTemplate="{DynamicResource DataTemplateButton}">

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接