I am trying to set up a sort of menu using ListBox and buttons as ListBoxItems to trigger a command when selection changes, but the result is that some times the selected ListBoxItem is changed but the command is not triggered, other times the opposite. The XAML is the following:
<Window.Resources>
<DataTemplate DataType="{x:Type viewModels:TripViewModel}">
<views:TripView />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:AddTripViewModel}">
<views:AddTripView />
</DataTemplate>
<Style TargetType="{x:Type Button}">
<Setter Property="Height"
Value="50" />
<Setter Property="Background"
Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border>
<Grid Background="Transparent">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Padding"
Value="3" />
<Setter Property="Background"
Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border BorderBrush="Transparent"
BorderThickness="0"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="DarkCyan" />
</Trigger>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Background"
Value="DarkCyan" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Window.Content>
<DockPanel Margin="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="Auto"
Width="Auto"
LastChildFill="True">
<!-- Left Panel -->
<Border BorderBrush="Black"
BorderThickness="0,0,1,0">
<StackPanel DockPanel.Dock="Left"
Margin="0"
Background="#555D6F">
<!-- First Row: Stacco Image -->
<Image Height="183"
Width="275"
Margin="3"
Source="/Media/stacco.png" />
<!-- Second Row: Buttons -->
<ScrollViewer CanContentScroll="True"
VerticalAlignment="Stretch"
VerticalScrollBarVisibility="Auto"
Margin="0,10,0,0">
<ListBox Name="MenuButtons"
ItemsSource="{Binding PageViewModels}"
Background="#555D6F"
IsSynchronizedWithCurrentItem="True">
<ListBox.ItemTemplate>
<ItemContainerTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Margin="0" />
</ItemContainerTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
</StackPanel>
</Border>
<!-- Control Area: Different View made by controls -->
<ContentControl DockPanel.Dock="Right"
Content="{Binding CurrentPageViewModel}" />
</DockPanel>
</Window.Content>
Am I doing right trying to insert a button in the ItemContainerTemplate? Would it be better to use the code behind to trigger the selection changed?
Related
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>
I have bumped into a problem to which I am seeking the solution.
I have a tabControl with styles added to it.
I want to display only images on each TabItem.Header and when that tab is selected then hide the image from header and display text (the other, inactive headers will be showing images).
Can anybody provide any help?
<Window.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid Name="Borderer" Background="#FF777777" Height="70" Width="90">
<ContentPresenter x:Name="ContentTabItem" ContentSource="Header" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="#FF000000" />
<Setter TargetName="Borderer" Property="Background" Value="WhiteSmoke" />
<Setter Property="Header" >
<Setter.Value>
<Grid>
<ContentPresenter ContentSource="Tag" />
</Grid>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TabControl Height="189" HorizontalAlignment="Left" Margin="94,123,0,0" Name="tabControl1" VerticalAlignment="Top" Width="500">
<TabItem Name="tabItem1" IsSelected="True" >
<TabItem.Tag>
<TextBlock Text="blab lab la" />
</TabItem.Tag>
<TabItem.Header>
<Image Source="images/img1.png" Width="35" Height="35" />
</TabItem.Header>
<TabItem.Content>
<Grid>
<TextBlock Name="aaa" />
</Grid>
</TabItem.Content>
</TabItem>
<TabItem >
<TabItem.Tag>
<TextBlock Text="la lab blab" />
</TabItem.Tag>
<TabItem.Header>
<Image Source="images/img2.png" Width="35" Height="35" />
</TabItem.Header>
<TabItem.Content>
<Grid>
<TextBlock Name="bbb" />
</Grid>
</TabItem.Content>
</TabItem>
</TabControl>
</Grid>
You can actually do this without replacing the whole ControlTemplate on the TabItem. You can just alter the TabItem's HeaderTemplate when the TabItem is selected, making your Style a lot shorter:
<DataTemplate x:Key="SelectedHeaderTemplate" >
<ContentControl Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=TabItem},
Path=Tag}" />
</DataTemplate>
<Style TargetType="{x:Type TabItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="HeaderTemplate" Value="{StaticResource SelectedHeaderTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
My Simple code for styling a ListBox and its Items:
<Style x:Key="SelectorPanelListBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="Background" Value="{x:Null}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Border.CornerRadius" Value="2"/>
<Setter Property="ItemTemplate" x:Name="MyItemTemplate">
<Setter.Value>
<DataTemplate >
<Border BorderBrush="White" BorderThickness="1" CornerRadius="5" OverridesDefaultStyle="True">
<Grid Height="57" Width="145">
<Label Content="{TemplateBinding Content}" />
<ContentControl Content="{Binding}" Foreground="White" />
</Grid>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Each of my Styles is stored as a resource library file in the resources section of my project, linked as "merged dictionaries" in a ResourceLibrary" master file, which is referenced by the App.xaml. That clearly is working because I already have many of these styles in use.
I use the styles in my views analogously to the following example:
<ListBox Style="{StaticResource SelectorPanelListBoxStyle}" ..../>
Unfortunately, The BorderBrush, BorderThickness, CornerRadius/etc only show up in the breadcrumbs editor in blend, and are NOT applied when style is actually used. Sometimes not even that. What am I doing wrong?
Thanks in advance!
I think you need to use a <ControlTemplate> instead of a <DataTemplate>. I would write your above style as:
<Style x:Key="SelectorPanelListBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="Background" Value="{x:Null}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Border.CornerRadius" Value="2"/>
<Setter Property="ItemTemplate" x:Name="MyItemTemplate">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="White" BorderThickness="1" CornerRadius="5" OverridesDefaultStyle="True">
<Grid Height="57" Width="145">
<Label Content="{TemplateBinding Content}" />
<ContentControl Content="{Binding}" Foreground="White" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
One of my own ListBox styles is below in case it might help you:
<Style TargetType="{x:Type ListBox}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="AllowDrop" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Border BorderThickness="0">
<ScrollViewer Margin="0">
<StackPanel Margin="0" IsItemsHost="True"/>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="GridViewTemplate">
<Border BorderBrush="LightBlue" BorderThickness="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" CornerRadius="0">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<DockPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<TextBlock FontFamily="Segoe UI Light" FontSize="18" Text="{Binding PropFullName}" Margin="2,2,2,2" DockPanel.Dock="Top"/>
<TextBlock FontFamily="Segoe UI Light" FontSize="18" Text="{Binding PropTitle}" Margin="2,2,2,2" DockPanel.Dock="Top"/>
</DockPanel>
</Grid>
</Border>
</DataTemplate>
The DataTemplate is then set as follows:
<ListBox.ItemTemplate>
<StaticResource ResourceKey="GridViewTemplate"/>
</ListBox.ItemTemplate>
EDIT 1:
<DataTemplate x:Key="MyListBoxTemplate">
<Border BorderBrush="White" BorderThickness="1" CornerRadius="5" OverridesDefaultStyle="True">
<Grid Height="57" Width="145">
<Label Content="{TemplateBinding Content}" />
<ContentControl Content="{Binding}" Foreground="White" />
</Grid>
</Border>
</DateTemplate>
<Style TargetType="{x:Type ListBox}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="AllowDrop" Value="True"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<StaticResource ResourceKey="MyListBoxItemTemplate"
</Setter.Value>
</Setter>
</Style>
Unable to drag the scroll bar after implementing custom scrollviewer on listbox in a usercontrol.
its working fine for other usercontrols which has listbox.
Only difference between usercontrols is WrapPanel
<!--ListBoxItem Style-->
<Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
<Setter
Property="FocusVisualStyle"
Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border
x:Name="ItemBorder"
BorderBrush="Transparent"
Background="Transparent"
BorderThickness="1" Margin="15"
>
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger
Property="IsSelected"
Value="True">
<Setter
TargetName="ItemBorder"
Property="Background"
Value="{StaticResource G2Brush}"/>
<Setter
TargetName="ItemBorder"
Property="BorderBrush"
Value="{StaticResource G4Brush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--ListBox Style-->
<Style TargetType="{x:Type ListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<ScrollViewer x:Name="ScrollViewer">
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border x:Name="border" Background="Transparent" Margin="2">
<Grid Width="70" Height="70">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Border x:Name="borderImage" Background="Transparent" Grid.Row="0">
<Image Source="{Binding Path=FilePath}" />
</Border>
<TextBlock x:Name="ThumbFileName" Text="{Binding Path=FileName}" Grid.Row="1"
Style="{StaticResource ThumbFileName}" VerticalAlignment="Top" HorizontalAlignment="Left"
TextTrimming="CharacterEllipsis"
/>
</Grid>
</Border>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="borderImage" Property="BorderBrush" Value="{StaticResource B1Brush}" />
<Setter TargetName="borderImage" Property="BorderThickness" Value="1" />
<Setter TargetName="ThumbFileName" Property="Foreground" Value="{StaticResource B1Brush}" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate >
<WrapPanel Margin="10"
Background="Red"
/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter
Property="ScrollViewer.HorizontalScrollBarVisibility"
Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
</Style>
<Grid Background="Transparent">
<ListBox x:Name="reportListViewControl"
Background="Transparent"
Foreground="{StaticResource G4Brush}"
BorderThickness="0"
Style="{StaticResource ListBoxStyle}"
ItemContainerStyle="{StaticResource ListBoxItemStyle}"
Drop="reportListViewControl_Drop"
SelectionMode="Extended"
SelectionChanged="reportListViewControl_SelectionChanged"
AllowDrop="True">
</ListBox>
</Grid>
In your example WrapPanel takes all the space it needs to show its items. To enable scrollbars you can restrict it by the size of its parent, ListBox:
<ItemsPanelTemplate>
<WrapPanel Margin="10" Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}"
Height="{Binding ActualHeight, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}"/>
</ItemsPanelTemplate>
Or you can use UniformGrid and control it with Columns or Rows property.