WPF: Alternating colors on a ItemsControl? - wpf

How do I get alternating colors on a ItemsControl? I have AlternationCount set to 2, but the ItemsControl.AlternationIndex property always returns 0.
<ItemsControl ItemsSource="{Binding}" AlternationCount="2">
<ItemsControl.Resources>
<Style x:Key="FooBar" TargetType="Grid">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Blue"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</ItemsControl.Resources>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,0,0,10" Style="{StaticResource FooBar}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions >
<RowDefinition Height="Auto" />
<!--<RowDefinition Height="Auto" />-->
</Grid.RowDefinitions>
<CheckBox IsChecked="{Binding Checked, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
<Label Grid.Column="1" Content="{Binding CompanyName}" />
<Label Grid.Column="2" Content="{Binding TradeKey}" />
<Label Grid.Column="3" Content="{Binding TradeDate}" ContentStringFormat="d" />
<Label Grid.Column="4" Content="{Binding Cusip}" />
<Label Grid.Column="5" Content="{Binding IssueName}" />
<Label Grid.Column="6" Content="{Binding TotalUnits}" ContentStringFormat="N0" />
<!--<Expander Grid.Row="0" Grid.Column="7" Grid.ColumnSpan="7" IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<Label Content="Allocations"/>
<Button Content="Edit" Name="cmdEdit" Click="cmdEdit_Click" />
</StackPanel>
</Expander.Header>-->
<DataGrid Grid.Column="7" IsReadOnly="True" ItemsSource="{Binding Territories}" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Rep on Ticket" Binding="{Binding TradeCustomer.RepNameNotes}" />
<DataGridTextColumn Header="Rep # on Ticket" Binding="{Binding TradeCustomer.RepNumberNotes}" />
<DataGridTextColumn Header="State" Binding="{Binding TradeCustomer.AccountStateKey}" />
<DataGridTextColumn Header="Qty. on Ticket" Binding="{Binding TradeCustomer.Quantity, StringFormat=N0}" />
<DataGridTextColumn Header="Zip Code" Binding="{Binding ZipCode}" />
<DataGridTextColumn Header="State" Binding="{Binding State}" />
<DataGridTextColumn Header="Territory" Binding="{Binding Territory}" />
</DataGrid.Columns>
</DataGrid>
<!--</Expander>-->
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="{TemplateBinding Control.Padding}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" SnapsToDevicePixels="True">
<ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>

Check here http://www.codeproject.com/Articles/35886/WPF-ItemsControl-with-alternating-items-and-hover-.aspx
You have to change your code like this to get it working
<ItemsControl ItemsSource="{Binding DataList}" AlternationCount="2">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid x:Name="FooBar" Margin="0,0,0,10">
----------------------------
----------------------------
</Grid>
<DataTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Blue" TargetName="FooBar"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="Red" TargetName="FooBar"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>

Here is an alternative which may be a bit more general
<DataTemplate x:Key="AlternatingTemplate">
<Border>
<Border.Style>
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
Value="0">
<Setter Property="Background" Value="White" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
Value="1">
<Setter Property="Background" Value="LightGray" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter Content="{Binding}" />
</Border>
</DataTemplate>
Usage:
<ItemsControl AlternationCount="2"
ItemTemplate="{StaticResource AlternatingTemplate}"
ItemsSource="{Binding SourceOfData}" />

If you don't want to use the DataTemplate approach, you can create a custom control that uses a ContentControl as the item container, therefore allowing you to specify a background color.
Class:
public class ItemsControlAlternating : ItemsControl
{
static ItemsControlAlternating()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ItemsControlAlternating),
new FrameworkPropertyMetadata(typeof(ItemsControlAlternating)));
}
protected override DependencyObject GetContainerForItemOverride()
{
return new ContentControl();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is ContentControl;
}
}
Resource Dictionary:
<Style TargetType="{x:Type c:ItemsControlAlternating}">
<Setter Property="AlternationCount" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type c:ItemsControlAlternating}">
<ItemsPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Gray"/>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>

Related

How can I set ScrollContentPresenter a backgroundcolor?

How can I give ScrollContentPresenter a backgroundcolor? is the same question, but I set the Background on the Parent of the ScrollContentPresenter. It is the Grid and it does not work for me. I can not change the background.
<Style x:Key="ScrollViewerStyle" TargetType="{x:Type ScrollViewer}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Border x:Name="border" BorderBrush="{Binding L1, Source={x:Static color:DesignBrushCollection.DesignColors}}" BorderThickness="1">
<Grid x:Name="Grid" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid Background="Red">
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" />
</Grid>
<ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"
Style="{DynamicResource ScrollBarStyle}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border"
Value="{Binding AC3, Source={x:Static color:DesignBrushCollection.DesignColors}}"/>
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border"
Value="{Binding AC3, Source={x:Static color:DesignBrushCollection.DesignColors}}"/>
<Setter Property="Background" TargetName="border"
Value="{Binding BG1, Source={x:Static color:DesignBrushCollection.DesignColors}}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" TargetName="border" Value="0.5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid Width="auto" Height="auto">
<Grid.RowDefinitions>
<RowDefinition Height="15" />
<RowDefinition Height="3" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<local:CommonLabel RequiredMark="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type local:CommonComboBox}},Path=RequiredMark}"
FontSize="13" Padding="0"
Content="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type local:CommonComboBox}},Path=Content}"
Grid.Row="0" Height="16" Width="139"
Margin="0,0,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Grid.ColumnSpan="2" />
<ScrollViewer Style="{StaticResource ScrollViewerStyle}" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Grid.Row="2">
<TextBox x:Name="TextField" TextWrapping="Wrap" BorderThickness="0" CaretBrush="{Binding AC3, Source={x:Static color:DesignBrushCollection.DesignColors}}"
Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:CommonTextField}},Path=Content,Mode=OneWay}" >
</TextBox>
</ScrollViewer>
</Grid>
</UserControl>
TextBox.Background does override the ScrollViewer.Background. If you set TextBox.Background = "Transparent" or TextBox.Background = "{x:Null}" you will see ScrollViewer.Background.
<TextBox x:Name="TextField" Background="Transparent" ... />
Be aware, that ScrollViewer.IsFocused set to true if you click the border of ScrollViewer or set the focus in code behind, not if you input a text in the TextBox.

Sort Caret Not Displaying

I'm having a problem where I'm using a provided style (I can alter it) and most times I get the sort caret, but in one case I don't.
This is the style:
<Style x:Key="StyleDataGridHeader" TargetType="DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="x:Type DataGridColumndHeader}">
<Grid x:Name="gridColumn background="{DynamicResource TableHeaderBackground}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock
x:name:"columnText" Grid.Column="0" HorizontalAlignment="Left" Background="{DynamicResource TableHeaderBackground}"
Focusable="False" Foreground="{DynamicResource TableHeaderFontColor}"
Text="{TemplateBinding Content}" />
<Path
x:Name"SortArrow" Grid.Column="0" Width="10" Height="10"
Fill="{DynamicResource TableColumnHeaderCaretColor}"
Focusable="False"
Style="{StaticResource CaretIconLeft}"
Visibility="Collapsed" />
<Thumb
x:Name="PART_LeftHeaderGripper"
Style="StaticResource ColumnHeaderGripStyle" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="SortDirection" Value="Ascending">
<Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
<Setter TargetName="columnText" Property="Foreground" Value="{DynamicResource TableColumnHeaderFocusColor}" />
<Setter TargetName="SortArrow" Property="LayoutTransform">
<Setter.value>
<RotateTransform Angle="180" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="SortDirection" Value="Decending">
<Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
<Setter TargetName="columnText" Property="Foreground" Value="{DynamicResource TableColumnHeaderFocusColor}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="columnText" Property="Foreground" Value="{DynamicResource TableColumnHeaderFocusColor}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here's an excerpt of the control with a column that works and a column that doesn't:
<UserControl
...
<Grid ...
<!-- This one works (sort caret displayed) -->
<DataGridTemplateColumn
Width="50"
SortMemberpath="ColA"
SortDirection="Ascending"
CellStyle="{StaticResource DataGridCellCenter}"
HeaderStyle="{StaticResource DataGridHeaderCenter}"
Header="COL-A">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Path Style="{StaticResource CircleIcon}" Fill="{Binding ColA}" />
</DataTemplate
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn
<!-- This one doesn't work (sort caret not displayed) -->
<DataGridTemplateColumn
Width="300"
SortMemberpath="ColB"
SortDirection="Ascending"
CellStyle="{StaticResource DataGridCellCenter}"
HeaderStyle="{StaticResource DataGridHeaderCenter}"
Header="COL-B">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding IconVals, Mode=OneWay}"/>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:StandardButtonControl
State="{Binding BState}"
Label="{Binding BLabel}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl />
</DataTemplate
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn
</Grid>
</UserControl>
The case where it doesn't work is a little more complex, but I can't figure out what's missing; any guidance would be appreciated.
SortDirection which you check in your triggers could start off as Null, and thus your Path will stay with Visibility Collapsed.

Menu and submenus using binding with Icon

I using this solution in order to bind my Menu just like at this example and I wonder how can I add icon to my MenuItem.
In my Model I also have property called IsSelected so I try this approach:
<Menu.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type Menu:MenuItemViewModel}" ItemsSource="{Binding Path=MenuItems}">
<StackPanel Orientation="Horizontal">
<Image Source="pack://application:,,,/Resources/checked_lightslategray.ico"
Width="12"
Height="12"
Margin="0,0,0,0">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<TextBlock Text="{Binding Description}" Margin="10,0,0,0"/>
</StackPanel>
</HierarchicalDataTemplate>
</Menu.ItemTemplate>
But this looks bad as you can see:
Any ideas how to move this image to the icon place on the left side of my MenuItem ?
Edit
This is the style i am using:
<Style TargetType="{x:Type Menu}" x:Key="StandardMenu">
<Style.Resources>
<Style x:Key="{x:Static MenuItem.SeparatorStyleKey}" TargetType="Separator">
<Setter Property="Height" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Separator">
<Border BorderBrush="{StaticResource MenuSeparatorBorderBrush}" BorderThickness="1" Margin="25,0,0,0"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}"/>
<Setter Property="FontSize" Value="{DynamicResource ApplicationFontSize}"/>
<Setter Property="Command" Value="{Binding Command}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<!--Border 1-->
<Border x:Name="Border" Background="Transparent" BorderBrush="Transparent" CornerRadius="2"
BorderThickness="1" SnapsToDevicePixels="False">
<Grid x:Name="Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Col0" MinWidth="17" Width="Auto" SharedSizeGroup="MenuItemIconColumnGroup"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="MenuTextColumnGroup"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup"/>
<ColumnDefinition x:Name="Col3" Width="14"/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" x:Name="Icon" VerticalAlignment="Center" ContentSource="Icon"/>
<ContentPresenter Grid.Column="1" Margin="{TemplateBinding Padding}" x:Name="HeaderHost" RecognizesAccessKey="True" ContentSource="Header" VerticalAlignment="Center"/>
<ContentPresenter Grid.Column="2" Margin="8,1,8,1" x:Name="IGTHost" ContentSource="InputGestureText" VerticalAlignment="Center"/>
<Grid Grid.Column="3" Margin="4,0,6,0" x:Name="ArrowPanel" VerticalAlignment="Center">
<Path x:Name="ArrowPanelPath" HorizontalAlignment="Right" VerticalAlignment="Center" Fill="{TemplateBinding Foreground}" Data="M0,0 L0,8 L4,4 z"/>
</Grid>
<Popup IsOpen="{Binding Path=IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
Placement="Right"
HorizontalOffset="-1"
x:Name="SubMenuPopup"
Focusable="false"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}"
AllowsTransparency="True">
<Grid Margin="0,0,5,5">
<!--Border 2-->
<Border x:Name="SubMenuBorder" CornerRadius="5"
BorderBrush="{StaticResource MenuSeparatorBorderBrush}"
BorderThickness="1"
Background="{StaticResource SubmenuItemBackground}"
SnapsToDevicePixels="True">
<Grid x:Name="SubMenu" Grid.IsSharedSizeScope="True" Margin="2">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
</Grid>
<Border.Effect>
<DropShadowEffect ShadowDepth="2" Color="Black"/>
</Border.Effect>
</Border>
<!--Border 3-->
<Border Margin="1,0,0,0"
x:Name="TransitionBorder"
Width="0"
Height="2"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Background="{StaticResource SubmenuItemBackground}"
SnapsToDevicePixels="False"
BorderThickness="1"
BorderBrush="{StaticResource SubmenuItemBackground}"/>
</Grid>
</Popup>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="Background" Value="{StaticResource LightBackground}"/>
<Setter Property="Foreground" Value="{StaticResource Foreground}"/>
</Style>
on image style trigger, you have set image visibility to collapsed which will release space required for the image and content will move to the left when there is no image visible.
there are two approaches to overcome this.
Option 1:
instead of visibility as Collapsed, go for visibility as Hidden.
<Menu.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type Menu:MenuItemViewModel}" ItemsSource="{Binding Path=MenuItems}">
<StackPanel Orientation="Horizontal">
<Image Source="pack://application:,,,/Resources/checked_lightslategray.ico"
Width="12"
Height="12"
Margin="0,0,0,0">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<TextBlock Text="{Binding Description}" Margin="10,0,0,0"/>
</StackPanel>
</HierarchicalDataTemplate>
</Menu.ItemTemplate>
Option 2:
- Use Header attribute to define your Description
- Use to define your image
<HierarchicalDataTemplate ItemsSource="{Binding Path=MenuItems}">
<MenuItem Header="{Binding Header}" ItemsSource="{Binding Path=MenuItems}" FontWeight="Bold">
<MenuItem.Icon>
<Image Source="pack://application:,,,/Resources/checked_lightslategray.ico">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</MenuItem.Icon>
<MenuItem.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</MenuItem.ItemsPanel>
</MenuItem>
</HierarchicalDataTemplate>
Put this to your Menu.Resources and delete Image from StackPanel:
<Menu.Resources>
<Image x:Key="img" x:Shared="false" Source="pack://application:,,,/Resources/checked_lightslategray.ico"/>
<Style TargetType="MenuItem">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="true">
<Setter Property="Icon" Value="{StaticResource img}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Menu.Resources>

MVVM Treeview Click Node

I am using an existed MVVM project and I did fine until now. I have a treeView code and I want
to release the node when it pressed. in other words, today if I click on any node, Its not selectable anymore (until you click another node). I want to be able to click thesame node as many times as I want. If I double click node , I have "IsExpended" property and it goes to this code section. I cant see where is the doubleclick bind, single click binding...
Here's the xaml
<UserControl x:Class="Envitech.Setup.Presentation.Views.TreeViewViews.StationTree" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:behaviour="clr-namespace:Envitech.Setup.Presentation.Extensions;assembly=Envitech.Setup.Presentation" xmlns:nodes="clr-namespace:Envitech.Setup.Presentation.ViewModels.TreeViewViewModels.Nodes" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="226" d:DesignWidth="227" xmlns:ml="clr-namespace:Envitech.Setup.Presentation.ml_resources">
<TreeView Margin="10 0 10 20" ItemsSource="{Binding Path=Root.Children}" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
<Setter Property="Padding" Value="1,0,0,0" />
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="behaviour:TreeViewItemBehavior.IsBroughtIntoViewWhenSelected" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="19" Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<ToggleButton x:Name="Expander" IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" />
<Border Grid.Column="1" x:Name="Selection_Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" x:Name="PART_Header" ContentSource="Header" />
</Border>
<ItemsPresenter Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1" x:Name="ItemsHost" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="false">
<Setter Property="Visibility" Value="Collapsed" TargetName="ItemsHost" />
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="Visibility" Value="Hidden" TargetName="Expander" />
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" TargetName="Selection_Border" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true" />
<Condition Property="IsSelectionActive" Value="false" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" TargetName="Selection_Border" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Style for the ToggleButton control used to expand/collapse a TreeViewItem control -->
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Focusable" Value="False" />
<Setter Property="Width" Value="19" />
<Setter Property="Height" Value="13" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Width="19" Height="13" Background="#00FFFFFF" x:Name="Border">
<Border Width="9" Height="9" x:Name="Border1" SnapsToDevicePixels="True" BorderBrush="#FF9495A2" BorderThickness="1,1,1,1" CornerRadius="1,1,1,1">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#FFFFFFFF" Offset="0.4" />
<GradientStop Color="#FFC6CEDA" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<Path Fill="#FF000000" Margin="1,1,1,1" x:Name="ExpandPath" Data="M0,2L0,3 2,3 2,5 3,5 3,3 5,3 5,2 3,2 3,0 2,0 2,2z" />
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Data" Value="M0,2L0,3 5,3 5,2z" TargetName="ExpandPath" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate DataType="{x:Type nodes:MonitorNode}">
<StackPanel Orientation="Horizontal" Margin="0 2 0 0">
<Image Source="{Binding ImageSource}" Width="16" Height="16" Margin="0 0 3 0" />
<TextBlock Text="{x:Static ml:MultiLang._157}" x:Name="ML_0048" />
<TextBlock Text="{Binding ID}" />
<TextBlock Text="{x:Static ml:MultiLang._158}" x:Name="ML_0050" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate DataType="{x:Type nodes:StationNode}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal" Margin="0 2 0 0">
<StackPanel.ContextMenu>
<ContextMenu HasDropShadow="True">
<MenuItem Header="{x:Static ml:MultiLang._160}" Command="{Binding CopyMonitorsCommand}" x:Name="ML_0055" />
<MenuItem Header="{x:Static ml:MultiLang._159}" Command="{Binding PasteMonitorsCommand}" x:Name="ML_0056" />
<MenuItem Header="{x:Static ml:MultiLang._162}" Command="{Binding CopyStationsCommand}" x:Name="ML_0057" />
<MenuItem Header="{x:Static ml:MultiLang._161}" Command="{Binding PasteStationsCommand}" x:Name="ML_0058" />
</ContextMenu>
</StackPanel.ContextMenu>
<Image Source="{Binding ImageSource}" Width="16" Height="16" Margin="0 0 3 0" />
<TextBlock Text="{x:Static ml:MultiLang._157}" x:Name="ML_0060" />
<TextBlock Text="{Binding ID}" />
<TextBlock Text="{x:Static ml:MultiLang._158}" x:Name="ML_0062" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type nodes:FilteringNode}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal" Margin="0 2 0 0">
<Image Source="{Binding ImageSource}" Width="16" Height="16" Margin="0 0 3 0" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</UserControl>
Thank you
When you double click a tree view item, it will be expanded. When it is expanded, your IsExpanded property will be changed due to your binding. Single clicking something that is NOT currently selected will change your IsSelected property. However, clicking it again (not double clicking) will NOT change the IsSelected property. Seems like what you want to do is to also add a 'Click' event handler. This way, each time it is clicked, you will be notified, not just when it is clicked for the first time when something else was selected.
To Accomplish this, add an for the 'MouseDoubleClick' event to your TreeViewItem style. If you want a single click, just do the same for the 'MouseDown' event:
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
<EventSetter Event="MouseDoubleClick" Handler="DoubleClickedItem"/>
</Style>
Once your XAML has the code above in it, right click your mouse on the word 'DoubleClickedItem' and select the 'NavigateToHandler' option and Visual Studio will generate a method stub for you in your code behind. You can then implement your double click behavior there.
This answer explains how to use the Interactivity extensions to remain fully MVVM.
WPF RightClick MouseBinding on release?
I've not been able to use the MouseLeftButtonDown event but MouseLeftButtonUp worked in my case (notification of a click on an already selected TreeViewItem).
I'm guessing that MouseLeftButtonDown is handled earlier in the event tree, so we never get to see it.

Can't figure out why some controls are being clipped

So I have buttons that extend beyond the grid they are in, but they only show up on mouse over. In some grids they render correctly and some they are rendered incorrectly. It seems to be consistent which ones are incorrect, but I cannot figure out why the issue occurs on those particular grids. I looked at the elements with snoop and can't see any issues with the properties as they are being rendered.
Correct rendering:
Incorrect rendering:
Here's the code
<ScrollViewer x:Name="GridItemScroller" Height="300">
<ItemsControl Margin="0,0" ItemsSource="{Binding Source={StaticResource rowItemsView}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid VerticalAlignment="Top" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Margin" Value="{Binding RowIndex, Converter={StaticResource IndexToPositionConverter}, ConverterParameter=20}" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate >
<Grid x:Name="itemPanel" VerticalAlignment="Top" ClipToBounds="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Grid.ColumnSpan="2" Fill="Transparent" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<CheckBox IsChecked="{Binding Path=Filtered, Converter={StaticResource NotConverter}}" Content="{Binding RowName}" />
<Canvas x:Name="CheckBoxButtonPanel" Grid.Column="1" ClipToBounds="False" VerticalAlignment="Center" Width="25" Height="2">
<Canvas.Style>
<Style TargetType="Canvas">
<Setter Property="Visibility" Value="Collapsed" />
<Setter Property="Panel.ZIndex" Value="0" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=itemPanel, Path=IsMouseOver}" Value="True">
<Setter Property="Visibility" Value="Visible" />
<Setter Property="Panel.ZIndex" Value="10" />
</DataTrigger>
</Style.Triggers>
</Style>
</Canvas.Style>
<Button HorizontalAlignment="Right" Height="15" Width="25" Canvas.Top="-15" local:ToolIcon.IconName ="{Binding Source={StaticResource LanguageInfo}, XPath=//Strings/#Up}" local:ToolIcon.Image="pack://application:,,,/CalUI;component/images/Up.png"
Style="{DynamicResource ToolIcon}" Click="Move_Up"/>
<Button HorizontalAlignment="Right" Height="15" Width="25" Canvas.Top="2" local:ToolIcon.IconName ="{Binding Source={StaticResource LanguageInfo}, XPath=//Strings/#Down}" local:ToolIcon.Image="pack://application:,,,/CalUI;component/images/Down.png"
Style="{DynamicResource ToolIcon}" Click="Move_Down"/>
</Canvas>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
Here's the XAML for the ToolIcon Style
<Style x:Key="ToolIcon" TargetType="{x:Type Button}">
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="ImageGrid">
<Grid.Effect>
<local:SaturationLuminanceEffect SaturationShift="0.95" LuminanceShift="0.8" />
</Grid.Effect>
<Image x:Name="image" RenderTransformOrigin="0.5,0.5" Source="{TemplateBinding local:ToolIcon.Image}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Effect" TargetName="ImageGrid">
<Setter.Value>
<local:SaturationLuminanceEffect SaturationShift="1" LuminanceShift="1.2" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Effect" TargetName="ImageGrid">
<Setter.Value>
<local:SaturationLuminanceEffect SaturationShift="1.05" LuminanceShift="1.0" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Effect" TargetName="ImageGrid">
<Setter.Value>
<local:SaturationLuminanceEffect SaturationShift="0.80" LuminanceShift="1.3" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
#CodeNaked had the following insight in a comment:
Clipping can be a tricky business. See this question for more info on the subject.
The question mentioned is «Why do my panels clip all the way around the panel when made smaller than the explicit size?»

Resources