【问题标题】:WPF Datagrid: Strange style behaviourWPF Datagrid:奇怪的样式行为
【发布时间】:2016-02-25 07:26:16
【问题描述】:

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

希望有人可以帮助我。提前致谢!

这是用户控件的代码摘录:

<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>

更新

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

[Here][2] 你看到圆角半径只显示在左侧,而不是右侧,因为溢出了。

更新 2

我想要实现的是this

附加信息:Datagrid 位于用户控件中,该控件绑定到 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>

【问题讨论】:

  • 你将如何解释这个:&lt;DataGrid.Resources&gt; &lt;Style TargetType="ScrollBar" BasedOn="{StaticResource ScrollBar}" /&gt; &lt;/DataGrid.Resources&gt;
  • 你的意思是滚动条样式的代码吗?我添加到上面的线程。

标签: c# wpf vb.net xaml datagrid


【解决方案1】:

尝试在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>

【讨论】:

  • 同样的效果,但我注意到了一些东西。我已将新图片附加到主帖。
  • @ms_dos 你不想在DataGridBorderImage 之间有空格?
  • 我希望 mouseOver 触发器的边框始终围绕整个行。但是当单元格的内容对于当前单元格宽度来说太大时,它会拉伸单元格宽度直到内容适合。即使该行溢出数据网格的边界。我用其他信息更新了主帖,也许它们有助于解决我的问题。
【解决方案2】:

好的,我解决了这个问题。看来我弄乱了数据网格的行样式模板,忘记给数据网格的DataGridTemplateColumn 定义宽度:

datagrid行样式模板中的ScrollViewer:

    <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>

感谢您的回答!

【讨论】: