WPF 数据网格:奇怪的样式行为

本文关键字:样式 数据 数据网 网格 WPF | 更新日期: 2023-09-27 18:36:04

我在 WPF 中的数据网格控件中有一个奇怪的行为。基本上,我将自定义对象添加到仅包含一列的数据网格中。在本专栏中,我将在堆栈面板中可视化图像和文本块。它工作正常,直到我定义图像的宽度。然后我明白了。

希望有人能帮助我。提前感谢!

下面是用户控件的代码摘录:

<Grid>
    <DataGrid Margin="2"
              CanUserResizeRows="False"
              AutoGenerateColumns="False"
              ItemsSource="{Binding dataGridRows}"
              SelectionChanged="selectionChanged"
              SelectionMode="Single"
              Style="{DynamicResource PaletteDataGrid}"
              ClipboardCopyMode="None"
              CanUserReorderColumns="False"
              CanUserResizeColumns="False"
              CanUserSortColumns="False"
              GridLinesVisibility="None"
              HeadersVisibility="None"
              HorizontalAlignment="Stretch"
              IsReadOnly="True"
              BorderBrush="{x:Null}"
              RowStyle="{DynamicResource PaletteRowStyle}"
              CellStyle="{DynamicResource PaletteDataGridCell}">
        <DataGrid.Resources>
            <Style TargetType="ScrollBar"
                   BasedOn="{StaticResource ScrollBar}" />
        </DataGrid.Resources>
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Image Source="{Binding itemImage}"
                                   MaxHeight="20"
                                   MaxWidth="20" />
                            <TextBlock Text="{Binding itemName}"
                                       VerticalAlignment="Center"
                                       Width="Auto"
                                       Margin="5, 0, 0, 0" />
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

数据网格的样式模板:

<Style x:Key="PaletteDataGrid"
       TargetType="{x:Type DataGrid}">
    <Setter Property="Background"
            Value="{StaticResource TabBackground}" />
    <Setter Property="Foreground"
            Value="{StaticResource TabItemActiveText}" />
    <Setter Property="BorderBrush"
            Value="Transparent" />
    <Setter Property="BorderThickness"
            Value="1" />
    <Setter Property="RowDetailsVisibilityMode"
            Value="VisibleWhenSelected" />
    <Setter Property="ScrollViewer.CanContentScroll"
            Value="true" />
    <Setter Property="ScrollViewer.PanningMode"
            Value="VerticalOnly" />
    <Setter Property="Stylus.IsFlicksEnabled"
            Value="False" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGrid}">
                <Border BorderBrush="Transparent"
                        BorderThickness="0,0,0,0"
                        Background="{StaticResource TabBackground}"
                        Padding="{TemplateBinding Padding}"
                        SnapsToDevicePixels="True">
                    <ScrollViewer x:Name="DG_ScrollViewer"
                                  Focusable="false">
                        <ScrollViewer.Template>
                            <ControlTemplate TargetType="{x:Type ScrollViewer}">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto" />
                                        <ColumnDefinition Width="*" />
                                        <ColumnDefinition Width="Auto" />
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="0" />
                                        <RowDefinition Height="*" />
                                        <RowDefinition Height="Auto" />
                                    </Grid.RowDefinitions>
                                    <Button Command="{x:Static DataGrid.SelectAllCommand}"
                                            Focusable="false"
                                            Style="{DynamicResource {ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}}"
                                            Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.All}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                            Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                                    <DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter"
                                                                    Grid.Column="1"
                                                                    Visibility="Hidden" />
                                    <ScrollContentPresenter x:Name="PART_ScrollContentPresenter"
                                                            CanContentScroll="{TemplateBinding CanContentScroll}"
                                                            Grid.Column="2"
                                                            Grid.Row="1" />
                                    <ScrollBar x:Name="PART_VerticalScrollBar"
                                               Grid.Column="0"
                                               Maximum="{TemplateBinding ScrollableHeight}"
                                               Orientation="Vertical"
                                               Grid.Row="1"
                                               Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
                                               Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
                                               ViewportSize="{TemplateBinding ViewportHeight}">
                                    </ScrollBar>
                                </Grid>
                            </ControlTemplate>
                        </ScrollViewer.Template>
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsGrouping"
                           Value="true" />
                <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping"
                           Value="false" />
            </MultiTrigger.Conditions>
            <Setter Property="ScrollViewer.CanContentScroll"
                    Value="false" />
        </MultiTrigger>
    </Style.Triggers>
</Style>
<Style x:Key="PaletteRowStyle"
       TargetType="{x:Type DataGridRow}">
    <Setter Property="Background"
            Value="Transparent" />
    <Setter Property="SnapsToDevicePixels"
            Value="true" />
    <Setter Property="Validation.ErrorTemplate"
            Value="{x:Null}" />
    <Setter Property="ValidationErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <TextBlock Foreground="Red"
                           Margin="2,0,0,0"
                           Text="!"
                           VerticalAlignment="Center" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridRow}">
                <Border x:Name="DGR_Border"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Background="{TemplateBinding Background}"
                        CornerRadius="2"
                        SnapsToDevicePixels="True"
                        Padding="5,5,5,5">
                    <SelectiveScrollingGrid>
                        <SelectiveScrollingGrid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                        </SelectiveScrollingGrid.ColumnDefinitions>
                        <SelectiveScrollingGrid.RowDefinitions>
                            <RowDefinition Height="*" />
                            <RowDefinition Height="Auto" />
                        </SelectiveScrollingGrid.RowDefinitions>
                        <DataGridCellsPresenter Grid.Column="1"
                                                ItemsPanel="{TemplateBinding ItemsPanel}"
                                                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        <DataGridDetailsPresenter Grid.Column="1"
                                                  Grid.Row="1"
                                                  SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                                  Visibility="{TemplateBinding DetailsVisibility}" />
                        <DataGridRowHeader Grid.RowSpan="2"
                                           SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                                           Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                    </SelectiveScrollingGrid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsNewItem"
                 Value="True">
            <Setter Property="Margin"
                    Value="{Binding NewItemMargin, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
        </Trigger>
        <Trigger Property="IsMouseOver"
                 Value="False">
            <Setter Property="Background"
                    Value="{StaticResource TabBackground}" />
            <Setter Property="BorderBrush"
                    Value="Transparent" />
            <Setter Property="BorderThickness"
                    Value="1,1,1,1" />
        </Trigger>
        <Trigger Property="IsMouseOver"
                 Value="True">
            <Setter Property="Background"
                    Value="{StaticResource ItemRolloverBackground}" />
            <Setter Property="BorderBrush"
                    Value="{StaticResource TabItemActiveBorder}" />
            <Setter Property="BorderThickness"
                    Value="1,1,1,1" />
        </Trigger>
    </Style.Triggers>
</Style>
<Style x:Key="PaletteDataGridCell"
       TargetType="{x:Type DataGridCell}">
    <Setter Property="Background"
            Value="Transparent" />
    <Setter Property="BorderBrush"
            Value="Transparent" />
    <Setter Property="BorderThickness"
            Value="0" />
    <Style.Triggers>
        <Trigger Property="IsSelected"
                 Value="True">
            <Setter Property="Background"
                    Value="Transparent" />
            <Setter Property="Foreground"
                    Value="{StaticResource TabItemActiveText}" />
            <Setter Property="BorderBrush"
                    Value="Transparent" />
        </Trigger>
        <Trigger Property="Selector.IsSelectionActive"
                 Value="False">
            <Setter Property="Background"
                    Value="Transparent" />
            <Setter Property="Foreground"
                    Value="{StaticResource TabItemActiveText}" />
            <Setter Property="BorderBrush"
                    Value="Transparent" />
        </Trigger>
        <Trigger Property="IsKeyboardFocusWithin"
                 Value="True">
        </Trigger>
        <Trigger Property="IsEnabled"
                 Value="false">
            <Setter Property="Foreground"
                    Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
        </Trigger>
    </Style.Triggers>
</Style>

滚动条样式:

<Style x:Key="ScrollBarLineButton"
       TargetType="{x:Type RepeatButton}">
    <Setter Property="SnapsToDevicePixels"
            Value="True" />
    <Setter Property="OverridesDefaultStyle"
            Value="true" />
    <Setter Property="Focusable"
            Value="false" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type RepeatButton}">
                <Border Name="Border"
                        Margin="1"
                        CornerRadius="2"
                        Background="{StaticResource TabItemActiveBorder}"
                        BorderBrush="{StaticResource TabItemActiveText}"
                        BorderThickness="1">
                    <Path HorizontalAlignment="Center"
                          VerticalAlignment="Center"
                          Fill="{StaticResource TabItemActiveText}"
                          Data="{Binding Path=Content,RelativeSource={RelativeSource TemplatedParent}}" />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed"
                             Value="true">
                        <Setter TargetName="Border"
                                Property="Background"
                                Value="{StaticResource TabItemActiveBorder}" />
                    </Trigger>
                    <Trigger Property="IsEnabled"
                             Value="false">
                        <Setter Property="Foreground"
                                Value="{StaticResource DisabledForegroundBrush}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="ScrollBarPageButton"
       TargetType="{x:Type RepeatButton}">
    <Setter Property="SnapsToDevicePixels"
            Value="True" />
    <Setter Property="OverridesDefaultStyle"
            Value="true" />
    <Setter Property="IsTabStop"
            Value="false" />
    <Setter Property="Focusable"
            Value="false" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type RepeatButton}">
                <Border Background="Transparent" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="ScrollBarThumb"
       TargetType="{x:Type Thumb}">
    <Setter Property="SnapsToDevicePixels"
            Value="True" />
    <Setter Property="Margin"
            Value="0,0,10,0" />
    <Setter Property="OverridesDefaultStyle"
            Value="true" />
    <Setter Property="IsTabStop"
            Value="false" />
    <Setter Property="Focusable"
            Value="false" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Thumb}">
                <Border CornerRadius="2"
                        Background="{StaticResource TabItemActiveBorder}"
                        BorderBrush="{StaticResource TabItemActiveBorder}"
                        BorderThickness="1" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<ControlTemplate x:Key="VerticalScrollBar"
                 TargetType="{x:Type ScrollBar}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.00001*" />
        </Grid.RowDefinitions>
        <Border Grid.RowSpan="1"
                CornerRadius="2"
                Background="{StaticResource TabBackground}"/>
            <Track Name="PART_Track"
               Grid.Row="1"
               IsDirectionReversed="true">
            <Track.DecreaseRepeatButton>
                <RepeatButton Style="{StaticResource ScrollBarPageButton}"
                              Command="ScrollBar.PageUpCommand" />
            </Track.DecreaseRepeatButton>
            <Track.Thumb>
                <Thumb Style="{StaticResource ScrollBarThumb}"
                       Margin="1,0,1,0"
                       Background="{StaticResource TabItemInactiveBackground}"
                       BorderBrush="{StaticResource TabItemInactiveBackground}" />
            </Track.Thumb>
            <Track.IncreaseRepeatButton>
                <RepeatButton Style="{StaticResource ScrollBarPageButton}"
                              Command="ScrollBar.PageDownCommand" />
            </Track.IncreaseRepeatButton>
        </Track>
    </Grid>
</ControlTemplate>
<Style x:Key="ScrollBar"
       TargetType="{x:Type ScrollBar}">
    <Setter Property="SnapsToDevicePixels"
            Value="True" />
    <Setter Property="OverridesDefaultStyle"
            Value="true" />
    <Style.Triggers>
        <Trigger Property="Orientation"
                 Value="Vertical">
            <Setter Property="Width"
                    Value="8" />
            <Setter Property="Height"
                    Value="Auto" />
            <Setter Property="Template"
                    Value="{StaticResource VerticalScrollBar}" />
        </Trigger>
    </Style.Triggers>
</Style>

更新

我注意到当我加载溢出当前单元格宽度的项目时,效果会消失。似乎单元格根据内容定义其宽度(这是合乎逻辑的)。但是,如何定义单元格的最大宽度不超过数据网格边界,最小宽度使用整个数据网格宽度?

[

这里][2]你可以看到角半径只显示在左侧,而不是在右侧,因为溢出。

更新 2

我想要实现的是这个。

其他信息:数据网格位于绑定到 TabControl 内容的用户控件中。以下是来自mainWindow.xaml的代码:

    <Grid Margin="0,96,0,0">
        <TabControl ItemContainerStyle="{StaticResource TabItem}"
                    TabStripPlacement="Right"
                    ItemsSource="{Binding loadedPalettes}"
                    Style="{StaticResource TabControl}"
                    Height="Auto"
                    SelectionChanged="paletteSelectionChanged"
                    SelectedIndex="{Binding selPaletteIndex}"
                    Width="Auto"
                    Margin="0,5,0,0">
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Header}">
                        <TextBlock.LayoutTransform>
                            <RotateTransform Angle="270" />
                        </TextBlock.LayoutTransform>
                    </TextBlock>
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <DataTemplate>
                        <my:tabDataGrid />
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>
    </Grid>

WPF 数据网格:奇怪的样式行为

尝试在 DataTemplate 中使用 Grid 而不是 StackPanel

<DataGrid.Columns>
   <DataGridTemplateColumn>
       <DataGridTemplateColumn.CellTemplate>
          <DataTemplate>
             <Grid>        
                <Grid.ColumnDefinitions>
                   <ColumnDefinition Width="Auto"/>
                   <ColumnDefinition Width="Auto"/>            
                </Grid.ColumnDefinitions>
                <Image Grid.Column="0" Source="{Binding itemImage}" MaxHeight="20" 
                       MaxWidth="20" />
                <TextBlock Grid.Column="1" Text="{Binding itemName}"
                                   VerticalAlignment="Center"
                                   Width="Auto"
                                   Margin="5, 0, 0, 0" />
             </Grid>
         </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
   </DataGridTemplateColumn>
</DataGrid.Columns>

好的,我解决了问题。似乎我搞砸了数据网格的行样式模板,忘记给数据网格的DataGridTemplateColumn一个定义的宽度:

数据网格行样式模板中的滚动查看器:

    <Setter Property="Template">
<Setter.Value>
    <ControlTemplate TargetType="{x:Type DataGridRow}">
        <Border x:Name="DGR_Border"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                Background="{TemplateBinding Background}"
                CornerRadius="2"
                SnapsToDevicePixels="True"
                Padding="5,5,5,5">
            <SelectiveScrollingGrid>
                <SelectiveScrollingGrid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </SelectiveScrollingGrid.ColumnDefinitions>
                <SelectiveScrollingGrid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </SelectiveScrollingGrid.RowDefinitions>
                <DataGridCellsPresenter Grid.Column="1"
                                        ItemsPanel="{TemplateBinding ItemsPanel}"
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                <DataGridDetailsPresenter Grid.Column="1"
                                          Grid.Row="1"
                                          SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                          Visibility="{TemplateBinding DetailsVisibility}" />
                <DataGridRowHeader Grid.RowSpan="2"
                                   SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                                   Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
            </SelectiveScrollingGrid>
        </Border>
    </ControlTemplate>
</Setter.Value>

userControl.xaml 中的数据网格列定义

    <DataGrid.Columns>
<DataGridTemplateColumn Width="*">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="20" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Image Source="{Binding itemImage}"
                       Grid.Column="0"
                       MaxHeight="20"
                       MaxWidth="20" />
                <TextBlock Text="{Binding itemName}"
                           Grid.Column="1"
                           Margin="5, 0, 0, 0" />
            </Grid>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

感谢您的回答!