问题
I was wondering if anyone has ever run into this situation. Basically what I'm trying to do is override the default listviewitem to customized the the selected background/foreground. I got that working all fine and dandy. Problem is, I noticed that on listviews where I have implemented gridviews the columns are broken. I'm not sure what's going on to break this. My approach to override the default style is used blend to get the full style by editing a copy of template. Modified it as needed. Applied it. This is pretty much what it looks like. Any thoughts?
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="Padding" Value="2,0,0,0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Bd" Property="BorderBrush" Value="{DynamicResource CustomBorderBrush}" />
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource CustomBackgroundBrush}" />
<Setter Property="Foreground" Value="{DynamicResource CustomForegroundBrush}" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true" />
<Condition Property="Selector.IsSelectionActive" Value="false" />
</MultiTrigger.Conditions>
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ListView Grid.Row="0" Grid.Column="0" Margin="15,15,0,0" Name="lstResources" SelectionChanged="lstResources_SelectionChanged">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn x:Name="column1" Header="column1" Width="100" CellTemplate="{StaticResource column1template}"/>
<GridViewColumn x:Name="column2" Header="column2" Width="100" CellTemplate="{StaticResource column2template}" />
<GridViewColumn x:Name="column3" Header="column3" Width="200" CellTemplate="{StaticResource column3template}" WPFUtility:GridViewColumnResize.Width="*"/>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<DataTemplate x:Key="column1template">
<DockPanel>
<TextBlock HorizontalAlignment="stretch" TextTrimming="CharacterEllipsis" >
<TextBlock.Text>
<Binding Path="mycontent"/>
</TextBlock.Text>
</TextBlock>
</DockPanel>
</DataTemplate>
回答1:
I inspected the control templates for the ListViews
in both cases, and came to the conclusion that the styling wasn't working for GridViews
because they require a GridViewRowPresenter to correctly layout the row data, rather than the ContentPresenter
.
Of course, if you do that, you'll find your normal ListViews
which don't use GridViews
no longer format correctly, because they require a ContentPresenter
.
I wasn't entirely sure of the neatest way around that, but stumbled across this blog post: http://www.steelyeyedview.com/2010/03/contentpresenter-gridviewrowpresenter.html
The gist of which I'll repeat here, in case it gets deleted:
His solution is a neat little hack, and seems to work. It makes use of both presenters, with the ContentPresenter
hidden by default (Visibility="Collapsed"
), and uses a trigger to make the ContentPresenter
visible if the GridViewRowPresenter
has no content. Since the GridViewRowPresenter
has no content, it won't show anything anyway.
Adapting your Style
to include his fix, you'd have something like this (Some code removed for focus):
<Style TargetType="{x:Type ListViewItem}">
<!-- Your Code -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<Grid>
<GridViewRowPresenter x:Name="gridrowPresenter"
Content="{TemplateBinding Property=ContentControl.Content}" />
<ContentPresenter x:Name="contentPresenter"
Content="{TemplateBinding Property=ContentControl.Content}" Visibility="Collapsed" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="GridView.ColumnCollection" Value="{x:Null}">
<Setter TargetName="contentPresenter" Property="Visibility" Value="Visible"/>
</Trigger>
<!-- Your Code -->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
来源:https://stackoverflow.com/questions/18700352/listviewitem-override-default-style-break-gridviews