I have a WPF ListView that contains a GridView. I want the selected row to look "flat" and not 3d style.
Dose anyone know how to do this?
Thanks,
Smadar
The 3D look is part of the default style. To change this you need to replace the ControlTemplate for ListViewItem. Here's a simple example which produces the following:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListView>
<ListView.View>
<GridView>
<GridViewColumn Header="A"/>
</GridView>
</ListView.View>
<ListView.Items>
<ListViewItem Content="Item 1"/>
<ListViewItem Content="Item 2"/>
<ListViewItem Content="Item 3"/>
</ListView.Items>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border CornerRadius="2" SnapsToDevicePixels="True"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<Border Name="InnerBorder" CornerRadius="1" BorderThickness="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="11" />
<RowDefinition />
</Grid.RowDefinitions>
<Rectangle Name="UpperHighlight" Visibility="Collapsed" Fill="#75FFFFFF" />
<GridViewRowPresenter Grid.RowSpan="2"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Grid>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightBlue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Window>
Note: The default templates are located here http://msdn.microsoft.com/en-us/library/ms788747.aspx. Since there is no way to change part of a ControlTemplate or base one off of an existing template, I usually try to keep as much of the default template as I can, and only change the parts I care about. It's a little verbose but should do what you're looking for.
Related
In my wpf application I have a listView with its view set to a gridView. I've defined separately borders for column headers and item cells but they are not inline with each other. In case I'm not too clear, here's an image of the problem:
The styles are as follows:
-> GridView columnHeader:
<Style TargetType="{x:Type GridViewColumnHeader}" x:Key="style_header">
<Setter Property="BorderBrush">
<Setter.Value>
<ImageBrush ImageSource="/images/black_line.png"/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<Grid SnapsToDevicePixels="true">
<Border x:Name="HeaderBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0,1,0,1" Background="{TemplateBinding Background}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="7"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Rectangle x:Name="UpperHighlight" Fill="#FFE3F7FF" Visibility="Collapsed"/>
<Border Padding="{TemplateBinding Padding}" Grid.RowSpan="2">
<ContentPresenter x:Name="HeaderContent" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0,0,0,1" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</Grid>
</Border>
<Canvas>
<Thumb x:Name="PART_HeaderGripper" Style="{StaticResource GridViewColumnHeaderGripper}"/>
</Canvas>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
-> ListView item:
<ListView x:Name="lstContent">
<ListView.View>
<GridView>
<!-- checkbox column -->
<GridViewColumn HeaderContainerStyle="{StaticResource style_header}">
<GridViewColumn.Header>
<TextBlock Text=""/>
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Border BorderBrush="{StaticResource imgBrushBorder}" BorderThickness="0,0,1,0" Margin="-6,-2,-6,-2">
<CheckBox Tag="{Binding Sync}" IsChecked="{Binding Sync}" Style="{StaticResource style_chkManagement}"/>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
This one is in static resources:
<ImageBrush x:Key="imgBrushBorder" ImageSource="/images/black_line.png"/>
Q: What is wrong and how can that be solved?
Any help highly appreciated.
I am creating a WPF custom control that inherits from ItemsControl. In the ControlTemplate of my control I have an ItemsPresenter. The problem is that I need to be able to get content in the items presenter to fill the entire content area. In the code below I have a simplified example of the broken code and also what I am trying to accomplish. BTW setting HorizontalAlignment and VerticalAlignment to Stretch causes the content expand horizontally but not vertically.
<Window x:Class="yada"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="768" Width="1024">
<Grid>
<Grid.Resources>
<Style TargetType="Border" x:Key="stepBorder">
<Setter Property="Background" Value="CadetBlue"></Setter>
<Setter Property="BorderBrush" Value="Green" ></Setter>
<Setter Property="BorderThickness" Value="2"></Setter>
<Setter Property="Padding" Value="25"></Setter>
</Style>
</Grid.Resources>
<TabControl Margin="0,20,0,0">
<TabItem Header="Broken">
<Border>
<ItemsControl>
<ItemsControl.Items>
<Control>
<Control.Template>
<ControlTemplate>
<Border Style="{StaticResource stepBorder}">
<TextBlock Text="Border fills small region near the top"></TextBlock>
</Border>
</ControlTemplate>
</Control.Template>
</Control>
</ItemsControl.Items>
</ItemsControl>
</Border>
</TabItem>
<TabItem Header="Works">
<Border>
<Control>
<Control.Template>
<ControlTemplate>
<Border Style="{StaticResource stepBorder}" >
<TextBlock Text="Border fills entire control"></TextBlock>
</Border>
</ControlTemplate>
</Control.Template>
</Control>
</Border>
</TabItem>
</TabControl>
</Grid>
</Window>
Here is some code from my control. I cant include it all, there is too much. I think this is the relevant part however:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Wizard}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" x:Name="ContentRow" />
<RowDefinition Height="{Binding ElementName= NavButtonPanel,Path=ActualHeight}"></RowDefinition>
</Grid.RowDefinitions>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" x:Name="ContentScrollViewer" MaxHeight="{Binding ElementName=ContentRowHeight, Path=ActualHeight}">
<ItemsPresenter
x:Name="Presenter"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
</ItemsPresenter>
</ScrollViewer>
<Border Style="{TemplateBinding NavButtonPanelStyle}" Grid.Row="1" x:Name="NavButtonPanel">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
</StackPanel>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate></DataTemplate>
</Setter.Value>
</Setter>
As usual, just posting on SO gets me halfway to my answer.
It turns out the ItemsControl is using an evil stackpanel as a container for items. Fortunately there is a top-secret property called ItemsPanel that lets you change this. Just set it to a grid as shown below and you are in business.
In my case I am writing a custom control that inherits from ItemsControl so in the Style I add this property setter:
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid></Grid>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
So I have a listview in which I set up drag and drop, but for some reason it only lets me drop inside the actual items in the listview, rather than on any portion of the controltemplate that I overrode. How do I make it so that I can also do drag and drop over the textblock containing the title for the column?
<ListView
Margin="0,4,0,0"
Grid.Column="0"
x:Name="NameListView"
HorizontalContentAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding Path = AddedItems}"
SelectionChanged="NameListView_SelectionChanged"
AllowDrop="True"
SelectionMode="Extended"
VirtualizingStackPanel.VirtualizationMode="Standard"
>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border
Name="Border"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true"
Background="Transparent"
>
<ContentPresenter
Content="{TemplateBinding Content}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border"
Property="Background" Value="{x:Static SystemColors.HighlightBrush}"
/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<EventSetter Event="PreviewMouseDoubleClick" Handler="NameListView_PreviewMouseDoubleClick"/>
</Style>
</ListView.ItemContainerStyle>
<!-- Until NET 4.0 Keygesture's cannot bind to a command, so the inputbindings must be set using static commands or with code behind-->
<ListView.Template>
<!--Template Defining the layout of this treeview-->
<ControlTemplate>
<Grid
Background="{TemplateBinding Background}"
>
<Grid.RowDefinitions>
<RowDefinition
Height="{Binding GraphHeight, Source={x:Static DaedalusGraphViewer:SettingsManager.AppSettings},
Converter={StaticResource GridLengthConverter}}"
/>
<RowDefinition Height="*"/>
<RowDefinition Height="18" />
</Grid.RowDefinitions>
<Border
Grid.ZIndex="1"
Grid.Row="0"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
>
<Grid>
<TextBlock
Foreground="{TemplateBinding Foreground}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Text="Signal Names"
/>
</Grid>
</Border>
<Canvas>
<Line
Grid.ZIndex="2"
x:Name="SelectedItemUnderline"
Stroke="Black"
StrokeThickness="3"
Visibility="Collapsed"
/>
</Canvas>
<ScrollViewer
Grid.ZIndex="1"
x:Name="SignalNameScrollViewer"
Grid.Row="1" Grid.RowSpan="2"
CanContentScroll="False"
VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Visible"
>
<ItemsPresenter />
</ScrollViewer>
</Grid>
</ControlTemplate>
</ListView.Template>
</ListView>
I had a first chance exception being handled inside the drag operation, so when I fixed that code, it allowed me to drop anywhere in the listview. Basically, if an exception is thrown in the drag handlers, the mouse cursor will display not available to drop and fail drop
I have an own control which derives from itemscontrol with an own template. I am using a Canvas inside the itemscontrol as ItemsPanel. Why f.e. on resize of the window the items also can be outside of the itemscontrol?
Templates:
<Style TargetType="{x:Type local:Dashboard}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Dashboard}">
<Grid>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
The items use this:
<Style TargetType="{x:Type local:Widget}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Widget}">
<Grid Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderThickness="2" BorderBrush="Black" Background="WhiteSmoke"
x:Name="Part_Header">
<ContentPresenter ContentSource="Header"/>
</Border>
<Border Grid.Row="1" BorderThickness="2" BorderBrush="Black" Background="WhiteSmoke">
<Grid>
<ContentPresenter />
<ResizeGrip x:Name="Part_Resize"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Cursor="SizeNWSE" />
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Depending on your alignment and margin settings, resizing a parent can cause children to move outside of a parent's boundaries. The easiest way I've found to check this is to load Blend and resize the parent, watching how contained controls move. By tweaking the anchors in Blend (which changes alignments and margins), you should be able to troubleshoot why they move.
I have created a TabControl in a WPF application I'm writing. I re-templated TabItem so that I could have a button on each tab header to close it. So far, all is well and good.
I decided that I now wanted shiny round buttons instead of the default square ugly things. Also, I wanted to use an image as my buttons content instead of simply setting the content to "X".
My XAML styles/templates:
<Style TargetType="{x:Type Button}" x:Key="EllipseButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Ellipse Fill="{TemplateBinding Background}"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{TemplateBinding BorderThickness}"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"/>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Button.Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="ClosableTabItemTemplate">
<DockPanel MinWidth="120" Margin="0,0,0,0">
<ContentPresenter
Content="{Binding Path=DisplayName}"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
<Button
Command="{Binding Path=UnSubscribeApplicationCommand}"
CommandParameter="{Binding Path=DisplayName}"
BorderBrush="Black"
BorderThickness="2"
VerticalContentAlignment="Center"
VerticalAlignment="Center"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
Width="16" Height="16">
<Image Source="closeicon.bmp" Height="8" Width="8"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Button.Style>
<Style TargetType="{x:Type Button}"
BasedOn="{StaticResource EllipseButtonStyle}">
<Setter Property="Background"
Value="{StaticResource CloseOffButtonBrush}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource CloseOnButtonBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DockPanel>
</DataTemplate>
With the above code in place, however, a selected tabs content (and the background as well) seems to shift upwards because of what I assume is the TabItems content moving upwards due to it being selected. Why, then, is the ellipse not shifting with the other content? Anyone have any idea what is going on here?
Sorry for the delayed response - I ended up solving the issue by modeling my TabItem template after the one posted in this blogpost. I believe the issue surfaced due to the fact that my TabItem template was being defined as a DataTemplate, not as a ControlTemplate as it should have been. Here is the new template:
<ControlTemplate x:Key="ClosableTabItemTemplate" TargetType="TabItem">
<Grid SnapsToDevicePixels="true">
<Border x:Name="Bd" Background="{StaticResource TabItemUnselectedBrush}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" >
<DockPanel x:Name="ContentPanel">
<Button Command="{Binding Path=UnSubscribeApplicationCommand}" BorderBrush="Black" HorizontalAlignment="Center" Margin="3,0,3,0" VerticalAlignment="Center" Width="16" Height="16" DockPanel.Dock="Right" ToolTip="Close Tab">
<Button.Content>
<Image Source="pack://application:,,,/Resources/Close.png" Height="8" Width="8" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Button.Content>
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource EllipseButtonStyle}">
<Setter Property="Background" Value="{StaticResource CloseOffButtonBrush}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource CloseOnButtonBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<ContentPresenter x:Name="Content" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{Binding Path=DisplayName}" RecognizesAccessKey="True" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}"/>
</DockPanel>
</Border>
</Grid>
<!-- bunch of ControlTemplate triggers to style the TabItem background color/position -->
</ControlTemplate>
Whenever I have controls inside a DockPanel, it always seems to play up if one of the controls I've explicitly attached DockPanel.Dock to comes AFTER the element I want to take up the fill portion. While I don't know if this will answer your question, try this instead in your ClosableTabItemTemplate DataTemplate:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0"/>
<Button Grid.Column="1"/>
</Grid>