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.
Related
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.
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>
I want to show Image inside of the Title of header in TabControl
This question(WPF TabItem - Image Binding) seems is right, but I have using Triggers and it doesn't help on my code.
Here is what I have Providing:
<TabControl Name="MainTabControl" Margin="0,28,0,0" TabStripPlacement="Top" >
<TabControl.Resources>
<Image x:Key="imgProfile" Source="/Icons/red icons/profile.png" />
<Image x:Key="imgComment" Source="Icons/red icons/notification.png" />
<Style TargetType="TabItem" >
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding}"
MouseDown="UIElement_OnMouseDown"
FontSize="18"
/>
<Image Height="25" Margin="4,0,4,0"
Source="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Tag.Source}" />
</WrapPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border Name="Border" BorderThickness="1,1,1,0" BorderBrush="Gainsboro" CornerRadius="0" Margin="2,0">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="5,2"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Border" Property="BorderBrush" Value="Transparent" />
<Setter TargetName="Border" Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource TabItemNormal}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabItem Name="tiProfile" Header="a" Tag="{StaticResource imgProfile}"></TabItem>
<TabItem Name="tiComment" Header="b" Tag="{StaticResource imgComment}"></TabItem>
</TabControl>
the binding from TabItem.HeaderTemplate to the TabItem.Tag must be via FindAncestor of TabItem type.
instead create Images in Resources, create BitmapImage, and bind it the Image.Source.
so, Resources:
<BitmapImage x:Key="imgProfile" Source="/Icons/red icons/profile.png" />
<BitmapImage x:Key="imgComment" Source="Icons/red icons/notification.png" />
Header DataTemplate:
<Image Height="25" Margin="4,0,4,0"
Source="{Binding Tag, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabItem}}}" />
I have a TabControl containing TabItems. I overwrote their ItemTemplate to contain:
A TextBlock showing the caption of the TabItem
A Button (X) which closes the tab
Now I would like to make the "X"-Button only visible, when the TabItem is either selected or the mouse is over it.
This is my XAML code so far...
<TabControl x:Name="tabControl"
ItemsSource="{Binding OpenedItems}">
<TabControl.ItemTemplate>
<DataTemplate>
<Grid Name="grid" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding TabCaption}"
Grid.Column="0"
Foreground="White"
HorizontalAlignment="Left"
Margin="3"
Name="label_TabTitle"
VerticalAlignment="Center" />
<Button Content="X"
Grid.Column="1"
Foreground="White"
HorizontalAlignment="Right"
Margin="3"
Name="button_close"
VerticalAlignment="Center"
Width="20"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Visibility="Hidden"
Click="button_close_Click_1">
</Button>
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter TargetName="button_close" Property="Visibility" Value="Visible"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Background" Value="#1C1C1C" />
<Setter Property="Content" Value="{Binding TabContentView}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid Name="Grid"
Background="{StaticResource GrayBrush}">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
RecognizesAccessKey="True">
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Grid" Property="Background" Value="{StaticResource BlueBrush}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Grid" Property="Background" Value="{StaticResource LightBlueBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
With the Trigger inside the DataTemplate it kind of works.. but: you have to hover the mouse directly over the Label in order to show the button. So basically, it is impossible to click the button, because it disappears again.
I would appreciate any help with these WPF Templates!
Thanks, Christian
It looks as though your TabItem does not have the background set so it is not catching the MouseOverEvent. Since the TextBlock has the foreground set and has text, it captures the MouseOverEvent. Try setting the Background child grid of the DataTemplate to Transparent and you should see that the MouseOverEvent will be caught and show the close button.
<TabControl x:Name="tabControl" ItemsSource="{Binding OpenedItems}">
<TabControl.ItemTemplate>
<DataTemplate>
<Grid Name="grid" VerticalAlignment="Center" Background="Transparent">
...
</Grid>
...
</DataTemplate>
</TabControl.ItemTemplate>
...
</TabControl>
If you set opacity instead of visibility it works. Removed all references to Visibility, changed to Opacity:
You may want to check my code edit. Not 100% sure it's a duplicate of what you had, but the idea works. Why? Not sure. :) I'm guessing the Hidden-Button was swallowing the MouseEnter events, but refusing to pass them on because it was hidden.
<TabControl x:Name="tabControl"
ItemsSource="{Binding OpenedItems}">
<TabControl.ItemTemplate>
<DataTemplate>
<Grid Name="grid" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding TabCaption}"
Grid.Column="0"
Foreground="White"
HorizontalAlignment="Left"
Margin="3"
Name="label_TabTitle"
VerticalAlignment="Center" />
<Button Content="X"
Grid.Column="1"
Foreground="White"
HorizontalAlignment="Right"
Margin="3"
Name="button_close"
VerticalAlignment="Center"
Width="20"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Opacity="0"
Click="button_close_Click_1">
</Button>
</Grid>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter TargetName="button_close" Property="Opacity" Value="1"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Background" Value="#1C1C1C" />
<Setter Property="Content" Value="{Binding TabContentView}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid Name="Grid"
Background="{StaticResource GrayBrush}">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
RecognizesAccessKey="True">
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Grid" Property="Background" Value="{StaticResource BlueBrush}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Grid" Property="Background" Value="{StaticResource LightBlueBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
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?»