So I have a ListViewItem style that I want to apply on the items (I just want to disable the disabled color Trigger on the listboxitems because it is ugly until/when I find a new color that I like better.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border
Name="Border"
Padding="2"
SnapsToDevicePixels="true"
Background="Transparent"
>
<GridViewRowPresenter
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>
However, upon adding this template to the listview, the items all shrink. Originally they were getting their item size from this binding (I think): Height={Binding ElementName=graph_viewer, Path=GraphHeight, Mode=OneWay}. However, I don't see any reason why adding an itemcontainer style would break this binding unless gridviewpresenter is doing something strange.
<HierarchicalDataTemplate
ItemsSource ="{Binding Path = bits}"
DataType="{x:Type ViewModels:BusViewModel}"
>
<Components:CenteredTextBlock
x:Name="CommentTextBlock"
BorderBrush="{Binding RelativeSource ={RelativeSource AncestorType={x:Type ListView}}, Path=BorderBrush}"
HorizontalAlignment="Stretch"
Height="{Binding ElementName=graph_viewer, Path=GraphHeight, Mode=OneWay}"
>
<Components:CenteredTextBlock.MainText>
<MultiBinding Converter="{StaticResource StringConcatConverter}">
<Binding Path="Alias" />
<Binding Path="SignalValueAtPrimaryMarker" />
</MultiBinding>
</Components:CenteredTextBlock.MainText>
</Components:CenteredTextBlock>
</HierarchicalDataTemplate>
CenteredTexTBlock is just a centered text block (wanted to save having to type out grid and write in alignment = center repeatedly).
<Grid>
<TextBlock
VerticalAlignment="Center"
HorizontalAlignment="Center"
Foreground="{Binding RelativeSource = {RelativeSource FindAncestor, AncestorType={x:Type Components:CenteredTextBlock}}, Path=Foreground}"
Text="{Binding RelativeSource = {RelativeSource FindAncestor, AncestorType={x:Type Components:CenteredTextBlock}}, Path=MainText}"
/>
</Grid>
Default template of ListViewItem has ContentPresenter and not GridViewRowPresenter.
In case you only want to disable selection Trigger and want your's brush over there, so i would suggest to have default ControlTemplate only with your set of Triggers in it.
Default template goes like this with your triggers:
<ControlTemplate
TargetType="ListViewItem">
<Border
BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
Name="Bd"
SnapsToDevicePixels="True">
<ContentPresenter
Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Bd"
Property="Background"
Value="{x:Static SystemColors.HighlightBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Related
I am trying to copy the IntelliJ Titlebar Menu in Windows as a learning exercise.
The default color changes of a WPF MenuItem seem to be:
Low Opacity blue background when "IsMouseOver" and not "IsSubmenuOpen"
Low Opacity blue background when "IsSubmenuOpen"
I would like to change this behavior to this (which can be observed in IntelliJ):
No color change when "IsMouseOver" and not "IsSubmenuOpen"
Dark blue background when "IsSubmenuOpen"
White foreground when "IsSubmenuOpen"
I have found code in this answer which is capable of doing this, but it also seems to disable the ability of the MenuItem to open its drop down box to reveal its children.
<Style x:Key="TitleBarMenuItem" TargetType="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter Content="{TemplateBinding Header}" Margin="35 5 10 5" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSubmenuOpen" Value="True">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="#2675BF"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I get these color changes without disabling the MenuItem functionality?
The problem you have there is that there's no popup for the sub menu. You're missing something like:
<Popup x:Name="Popup"
Placement="Right"
HorizontalOffset="-4"
IsOpen="{TemplateBinding IsSubmenuOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Fade">
<Border x:Name="SubmenuBorder"
SnapsToDevicePixels="True"
Background="{DynamicResource MenuPopupBrush}"
BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
<ScrollViewer CanContentScroll="True"
Style="{StaticResource MenuScrollViewer}">
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Cycle" />
</ScrollViewer>
</Border>
</Popup>
Note that "IsItemsHost".
If you take a look at the templates for menu and menuitem you will notice it is very complicated stuff.
The approach I prefer is to work with content. You can put pretty much anything you like in a menuitem header.
One app I have does so with hard coded xaml. That's easier to understand than binding anyhow. Part of it looks like:
<MenuItem Header="_Layers" Style="{x:Null}">
<MenuItem>
<MenuItem.Header>
<CheckBox IsChecked="{Binding ShowBackground, Mode=TwoWay}">
_Background
</CheckBox>
</MenuItem.Header>
<MenuItem>
<MenuItem.Header>
<StackPanel Width="160">
<TextBlock Text="Opacity" />
<Slider Value="{Binding BackgroundOpacity, Mode=TwoWay}" />
</StackPanel>
</MenuItem.Header>
</MenuItem>
</MenuItem>
<MenuItem>
<MenuItem.Header>
<CheckBox IsChecked="{Binding AppSettings.ShowElevationMap, Mode=TwoWay}">
_Elevation Map
</CheckBox>
</MenuItem.Header>
<MenuItem>
<MenuItem.Header>
<StackPanel Width="160">
<TextBlock Text="Opacity" />
<Slider
Value="{Binding AppSettings.ElevationOpacity, Mode=TwoWay}" />
</StackPanel>
</MenuItem.Header>
Layers is a top level menu item. These are templated different to their children. ( Did I mention menus are complicated ).
I offset the content so I don't need to worry about the icon column in the grid.
The styling I have might be useful to get you started.
You said this was a learning exercise so just doing it for you is presumably not exactly going to exercise your learning.
<ItemsPanelTemplate x:Key="MenuItemPanelTemplate">
<StackPanel Margin="-20,0,0,0" Background="White"/>
</ItemsPanelTemplate>
<Style TargetType="MenuItem" x:Key="MenuItemNoIcon">
<Setter Property="ItemsPanel" Value="{StaticResource MenuItemPanelTemplate}"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
<Style TargetType="{x:Type MenuItem}" x:Key="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border x:Name="templateRoot" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{x:Static SystemColors.MenuBarBrush}"
SnapsToDevicePixels="True">
<Grid Margin="-1, 2, 0, 2">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="MenuItemIconColumnGroup" Width="0"/>
<ColumnDefinition Width="0"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="0"/>
<ColumnDefinition SharedSizeGroup="MenuItemIGTColumnGroup" Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}"
Grid.Column="2" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" HorizontalAlignment="Left" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
<TextBlock Grid.Column="4" Margin="{TemplateBinding Padding}" Opacity="0.7" Text="{TemplateBinding InputGestureText}" VerticalAlignment="Center"/>
<Path x:Name="RightArrow" Grid.Column="5" Width="10" Data="M0,0L4,3.5 0,7z" Fill="#FF212121" Margin="8,0,2,0" VerticalAlignment="Center"/>
<Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" HorizontalOffset="-2"
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Right" VerticalOffset="-3">
<Border x:Name="SubMenuBorder" BorderBrush="#FF999999" BorderThickness="1" Background="#FFF0F0F0" Padding="2">
<ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle"
Grid.IsSharedSizeScope="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
</Grid>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation" Value="True">
<Setter Property="PopupAnimation" TargetName="PART_Popup" Value="None"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" TargetName="templateRoot" Value="Transparent"/>
<Setter Property="BorderBrush" TargetName="templateRoot" Value="#FF26A0DA"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="#FF707070"/>
<Setter Property="Fill" TargetName="RightArrow" Value="#FF707070"/>
</Trigger>
<DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource Self}}" Value="0">
<Setter Property="Visibility" TargetName="RightArrow" Value="Collapsed"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have an Expander and it should receive the full width of the column but I cant get it to work.
I tried to add the Horizontal(Content)Alignment = stretch on the TextBlock and on the Expander itself even on the Grid, but it is not working.
What I need is that the Expander takes about 90% of the width and the rest are assigned to the buttons as in the following example:
I want to display e.g. a name and when you press on it, expands down and shows additional information
and if the buttons are pressed, then the commands behind the buttons will be executed (no commands are binded in the example).
<ListView
ItemsSource="{Binding log}"
SelectionMode="Multiple"
Style="{StaticResource ListViewStyle}">
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1" BorderBrush="Gray">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100*" />
<ColumnDefinition Width="5*" />
<ColumnDefinition Width="5*" />
</Grid.ColumnDefinitions>
<Expander Grid.Column="0"
HorizontalAlignment="Stretch"
IsExpanded="{Binding Mode=TwoWay, Path=IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}"
Style="{StaticResource ExpanderStyle}">
<Expander.Header>
<TextBlock Text="{Binding Name}" Foreground="White"
HorizontalAlignment="Stretch" />
</Expander.Header>
<TextBlock
VerticalAlignment="Center"
FontSize="16"
Foreground="White"
Text="{Binding Description}" />
</Expander>
<Button Grid.Column="1"
Style="{StaticResource IconButton}">
<Button.Background>
<ImageBrush ImageSource="../icons/edit.png"
Stretch="None" />
</Button.Background>
</Button>
<dialogButton:ConfirmButton Grid.Column="2"
Question="{x:Static language:Strings.confirm}"
Style="{DynamicResource IconButton}"
Margin="0,0,10,0">
<dialogButton:ConfirmButton.Background>
<ImageBrush ImageSource="../icons/delete.png"
Stretch="None" />
</dialogButton:ConfirmButton.Background>
</dialogButton:ConfirmButton>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Styles
<Style x:Key="ExpanderDownHeaderStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Padding="{TemplateBinding Padding}">
<Grid Background="Transparent" SnapsToDevicePixels="False">
<ContentPresenter HorizontalAlignment="Stretch" Margin="0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ExpanderStyle" TargetType="{x:Type Expander}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="3" SnapsToDevicePixels="true">
<DockPanel>
<ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}" DockPanel.Dock="Top" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontWeight="{TemplateBinding FontWeight}" FocusVisualStyle="{StaticResource ExpanderHeaderFocusVisual}" FontFamily="{TemplateBinding FontFamily}" Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" MinHeight="0" MinWidth="0" Margin="1" Padding="{TemplateBinding Padding}" Style="{StaticResource ExpanderDownHeaderStyle}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
<ContentPresenter x:Name="ExpandSite" DockPanel.Dock="Bottom" Focusable="false" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Visibility="Collapsed"/>
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="true">
<Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
</Trigger>
<Trigger Property="ExpandDirection" Value="Down">
<Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Bottom"/>
<Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Top"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderDownHeaderStyle}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I also tried things from the following Threads
wpf - Header of Expander fit contents width?
Problem here is that the Buttons are pushed out of the view
Best Solution would be if the Expander just takes the width of the column so that I can adjust the widths of the element by the Grid.ColumnDefinition.
The issue is that the item container, a ListViewItem does not stretch its content by default. You have to create an item container style in order to set the HorizontalContentAlignment to Stretch.
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
I have a WPF ListView inside StackPanel, with Height="Auto". It's great that it does what I wanted to - changes it's height according to the all items contained in ListView. I have also HorizontalScrollBarVisiblity="Auto" on my ListView, which suits my needs.
The problem occurs when the whole width of columns of my ListView is greater than width of ListView control (i.e. user decreases width of a window and this control). In that case obviously horizontal scrollbar appears - thats ok. The problem is that this scrollbar covers last (bottom) item of the ListView's items so it is partially not visible.
Vertical scrollbar doesn't appear and this is ok - I don't want it. I just want to have my ListView height beeing calculated properly, so it considers the height of shown horizontal scrollbar and includes it in calculation so all items are wholy visible.
Xaml code example:
<ListView Name="lvProcedures" ItemsSource="{Binding Path=Procedures}" SelectionMode="Single">
<ListView.View>
<GridView AllowsColumnReorder="False" ColumnHeaderToolTip="Lista zabiegów">
<GridViewColumn DisplayMemberBinding="{Binding Path=procedure}" Header="A" Width="150" />
<GridViewColumn DisplayMemberBinding="{Binding Path=location}" Header="B" Width="100" />
<GridViewColumn DisplayMemberBinding="{Binding Path=material}" Header="C" Width="180" />
<GridViewColumn DisplayMemberBinding="{Binding Path=other}" Header="D" Width="180" />
<GridViewColumn DisplayMemberBinding="{Binding Path=description}" Header="E" Width="400" />
</GridView>
</ListView.View>
</ListView>
I've now hanged on idea to create user control (maybe only ListView's derieved class??) which overrides MeasureOverride but I don't think it is good way to solve such a small but iritating "bug" and it also still makes me trouble to implement the solution.
Can somebody provide some elegant solution for this problem?
Any idea would be appreciated.
#bartivo: I'm not getting the same result as you - the bottom horizontal scrollbar doesn't appear to obscure the lowest item. I'm wondering if you're using a custom ControlTemplate for your ListView and ScrollViewer, b/c the default ScrollViewer template has two rows the ScrollContentPresenter in the first (Height="*") and the HorizontalScrollBar in the 2nd row (Height="Auto") thus ensuring that the one doesn't overlap the other.
Maybe you could try using these styles for your ListView and ScrollViewer and see if that problem still occurs:
<SolidColorBrush x:Key="ListBorder" Color="#828790"/>
<Style x:Key="{x:Static GridView.GridViewScrollViewerStyleKey}" TargetType="{x:Type ScrollViewer}">
<Setter Property="Focusable" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid SnapsToDevicePixels="true" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel Margin="{TemplateBinding Padding}">
<ScrollViewer Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" DockPanel.Dock="Top">
<GridViewHeaderRowPresenter Margin="2,0,2,0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" AllowsColumnReorder="{Binding TemplatedParent.View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContainerStyle="{Binding TemplatedParent.View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContextMenu="{Binding TemplatedParent.View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderStringFormat="{Binding TemplatedParent.View.ColumnHeaderStringFormat, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplate="{Binding TemplatedParent.View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplateSelector="{Binding TemplatedParent.View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderToolTip="{Binding TemplatedParent.View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}" Columns="{Binding TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}"/>
</ScrollViewer>
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.DirectionalNavigation="Local" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" CanContentScroll="{TemplateBinding CanContentScroll}"/>
</DockPanel>
<ScrollBar x:Name="PART_HorizontalScrollBar" Cursor="Arrow" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Grid.Row="1" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0.0" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}"/>
<ScrollBar x:Name="PART_VerticalScrollBar" Cursor="Arrow" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0.0" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}"/>
<DockPanel Background="{Binding Background, ElementName=PART_VerticalScrollBar}" Grid.Column="1" Grid.Row="1" LastChildFill="false">
<Rectangle Fill="White" Width="1" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" DockPanel.Dock="Left"/>
<Rectangle Fill="White" Height="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" DockPanel.Dock="Top"/>
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ListViewStyle1" TargetType="{x:Type ListView}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource ListBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="#FF042271"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListView}">
<Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}">
<ScrollViewer Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}" Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Microsoft_Windows_Themes:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have an issue when designing a inherited Expander. My intention is to have a progress bar behind the toggle button and text in the default Expander header.
I have this XAML code which gives me the progress bar in the header. It is a custom style.
<Style x:Key="CurrentScanExpanderStyle" TargetType="{x:Type local:ProgressExpander}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ProgressExpander}">
<Border SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3">
<DockPanel>
<Grid DockPanel.Dock="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ProgressBar Name="ProgressBar"/>
<ToggleButton FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" FontStretch="{TemplateBinding FontStretch}" FontStyle="{TemplateBinding FontStyle}" FontWeight="{TemplateBinding FontWeight}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" FocusVisualStyle="{StaticResource ExpanderHeaderFocusVisual}" Margin="1" MinHeight="0" MinWidth="0" x:Name="HeaderSite" Style="{StaticResource ExpanderDownHeaderStyle}" IsChecked="{Binding Path=IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Content="{TemplateBinding Header}" ContentTemplate="{TemplateBinding HeaderTemplate}" ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"/>
</Grid>
<ContentPresenter Focusable="false" Visibility="Collapsed" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" x:Name="ExpandSite" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" DockPanel.Dock="Bottom"/>
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<!-- Triggers haven't changed from the default -->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
this works fine but I am having trouble binding my custom dependency property which controls the progress percentage.
public class ProgressExpander : Expander
{
static ProgressExpander()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ProgressExpander), new FrameworkPropertyMetadata(typeof(ProgressExpander)));
}
public int Progress
{
get { return (int)GetValue(ProgressProperty); }
set { SetValue(ProgressProperty, value); }
}
// Using a DependencyProperty as the backing store for Progress. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ProgressProperty =
DependencyProperty.Register("Progress", typeof(int), typeof(ProgressExpander), new UIPropertyMetadata(0));
}
This is the code inside of the window:
<local:ProgressExpander Grid.Row="1" Header="Current Scan" ExpandDirection="Down" x:Name="currentScanExpander" Style="{DynamicResource CurrentScanExpanderStyle}">
<Canvas Background="SkyBlue"
Name="currentScanCanvas"
Height="{Binding ElementName=currentScanExpander, Path=ActualWidth}"
/>
</local:ProgressExpander>
I'm not sure how to bind this dependency property progress to the progress value in the ProgressBar within the style.
Any help would be appreciated.
In the style, we can use a standard Binding with a RelativeSource to set up the property.
<ProgressBar Name="ProgressBar"
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Progress}"
Minimum="0"
Maximum="100" />
Then, in the window we just add Progress="50" or a binding to somewhere else.
You will also need to set the Button's background to transparent, or change some manner of the layout, in order to see it.
I've been working on a SplitButton control for WPF and its basically done, but I'm trying to go through all the possible properties that can be set on it and make sure they are actually implemented. I mostly have only two properties left to implement which is the ItemTemplate and ItemTemplateSelector (and AlternationCount, okay so 3 properties).
I was able to get the HeaderTemplate and HeaderTemplateSelector working by binding the ContentTemplate and ContentTemplateSelector to them on a ContentPresenter. This is for the button part of the control though. For the drop-drop part of the control I'm using a Popup, Border, and ItemsPresenter. The problem is that I can't figure how to set the ItemTemplate and ItemTemplateSelector properties for the ItemsPresenter.
Any ideas?
Update:
The full source code for the SplitButton is now available at:
http://anothersplitbutton.codeplex.com/
Here's the Luna.NormalColor.xaml file:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:WpfSplitButton="clr-namespace:WpfSplitButton"
xmlns:mwt="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Luna"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- SplitButtonHeader Style -->
<Style x:Key="{x:Type WpfSplitButton:SplitButtonHeader}"
TargetType="{x:Type WpfSplitButton:SplitButtonHeader}">
<Style.Resources>
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2"
StrokeThickness="1"
Stroke="Black"
StrokeDashArray="1 2"
SnapsToDevicePixels="True" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Style.Setters>
<Setter Property="FocusVisualStyle"
Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="PastLeftDetection"
Value="True" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<mwt:ButtonChrome x:Name="Chrome"
BorderBrush="{TemplateBinding Border.BorderBrush}"
RenderDefaulted="{TemplateBinding Button.IsDefaulted}"
RenderMouseOver="{TemplateBinding UIElement.IsMouseOver}"
RenderPressed="{TemplateBinding ButtonBase.IsPressed}"
SnapsToDevicePixels="True">
<Grid Background="{TemplateBinding ButtonBase.Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ButtonBase.ContentTemplate}"
ContentTemplateSelector="{TemplateBinding ButtonBase.ContentTemplateSelector}"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
Margin="{TemplateBinding Control.Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" />
<Border x:Name="PART_DropDownInitiator"
Background="Transparent"
BorderBrush="{Binding Path=BorderBrush, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButtonHeader}}}"
BorderThickness="1,0,0,0"
Grid.Column="1"
HorizontalAlignment="Stretch"
Margin="0,0,0,0"
Padding="4,0,4,0"
VerticalAlignment="Stretch">
<Path Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButtonHeader}}}"
VerticalAlignment="Center">
<Path.Style>
<Style>
<Setter Property="Path.Fill"
Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Style.Triggers>
<Trigger Property="WpfSplitButton:SplitButton.IsMouseOver"
Value="True">
<Setter Property="Path.Fill"
Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
</Trigger>
</Style.Triggers>
</Style>
</Path.Style>
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure IsClosed="True"
StartPoint="0,0">
<PathFigure.Segments>
<PathSegmentCollection>
<LineSegment Point="8,0" />
<LineSegment Point="4,5" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Border>
</Grid>
</mwt:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsKeyboardFocused"
Value="True">
<Setter TargetName="Chrome"
Property="mwt:ButtonChrome.RenderDefaulted"
Value="True" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked"
Value="True">
<Setter TargetName="Chrome"
Property="mwt:ButtonChrome.RenderPressed"
Value="True" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
<!-- SplitButton -->
<Style x:Key="{x:Type WpfSplitButton:SplitButton}"
TargetType="{x:Type WpfSplitButton:SplitButton}">
<Style.Resources>
<LinearGradientBrush x:Key="ButtonNormalBackgroundFill"
EndPoint="0.5,1"
StartPoint="0.5,0">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FFFFFFFF"
Offset="0" />
<GradientStop Color="#FFF0F0EA"
Offset="0.9" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonBorder"
Color="#FF003C74" />
</Style.Resources>
<Setter Property="AutoUpdateHeader"
Value="True" />
<Setter Property="Background"
Value="{StaticResource ButtonNormalBackgroundFill}" />
<Setter Property="BorderBrush"
Value="{StaticResource ButtonBorder}" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="Padding"
Value="4,4,4,4" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type WpfSplitButton:SplitButton}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<WpfSplitButton:SplitButtonHeader x:Name="PART_Header"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
Cursor="{TemplateBinding Cursor}"
Foreground="{TemplateBinding Foreground}"
Grid.Row="0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Stretch"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
<Popup x:Name="PART_Popup"
AllowsTransparency="True"
Grid.Row="1"
IsOpen="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
MinWidth="{Binding Path=ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButton}}}"
Placement="Bottom"
PlacementTarget="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButton}}}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}"
StaysOpen="False">
<mwt:SystemDropShadowChrome Color="Transparent">
<Border x:Name="DropDownBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</mwt:SystemDropShadowChrome>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled"
Value="False">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Update 2
I tried switching out the ItemsPresenter with a ItemsControl, but I can't seem to get the ItemTemplate property to do anything. Here's the changed section of code:
<ItemsControl DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButton}}}"
AlternationCount="{TemplateBinding AlternationCount}"
IsTabStop="{TemplateBinding IsTabStop}"
IsTextSearchEnabled="{TemplateBinding IsTextSearchEnabled}"
ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
ItemContainerStyleSelector="{TemplateBinding ItemContainerStyleSelector}"
ItemBindingGroup="{TemplateBinding ItemBindingGroup}"
ItemsPanel="{TemplateBinding ItemsPanel}"
ItemsSource="{Binding Path=Items}"
ItemStringFormat="{TemplateBinding ItemStringFormat}"
ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="HELLO" />
</DataTemplate>
</ItemsControl.ItemTemplate>
Have you considered using an ItemsControl instead of the ItemsPresenter? This would give you the ItemTemplate and ItemTemplateSelector property as well as the AlternationCount property.
Update:
I got it to work just fine using the ItemsControl like you posted above using the following line to bind to the ItemsTemplate Property in your Classic.xaml file:
ItemTemplate="{TemplateBinding ItemsTemplate, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WpfSplitButton:SplitButton}}}"
Then in your MainWindow's Resources i just added the following template:
<DataTemplate x:Key="Test">
<MenuItem Header="{Binding}" />
</DataTemplate>
Then i set the ItemTemplate Property on the SplitButton:
ItemTemplate="{StaticResource Test}"
So just hook up your ItemSource and you are good to go... i just used a simple string[] in the code behind...
Hope this helps!