Combobox WPF template item and selected item - c#

I try to do a template for a combobox. The ItemTemplate is ok but not the selected item as u can see below:
My code:
<ComboBox ItemsSource="{Binding CouleursList}"
SelectedItem="{Binding SelectedCouleur}"
Grid.Column="1" Grid.Row="2">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ComboBox.ItemContainerStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Rectangle Stroke="Black" Margin="1" Height="15"
HorizontalAlignment="Stretch">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding Path=., Converter={StaticResource ColorConverter}}"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
If I gave a fixed width, that works but the rectangle is align to the left and center for the list
Thanks !

The selected item content isn't displayed in a ComboBoxItem, so your HorizontalContentAlignment style setter won't apply.
You can set that property on the ComboBox itself, however:
<ComboBox
ItemsSource="{Binding CouleursList}"
SelectedItem="{Binding SelectedCouleur}"
HorizontalContentAlignment="Stretch"

Related

Remove hover effect on parent listbox item on hover of child listbox item WPF

I have started learning the WPF. I am facing the problem regarding hover effect on the list box.
I have used the list box control. Inside that control, I have added toggle button and On toggle button click I have bound the other list box.
Say,
Listbox -> Toggle button -> Listbox
I would like to remove parent (Name) list box item boarder hover effect when I hover over the title.
I have searched a lot but didn't found any hits how can remove parent hover effect from child element.
Here is the code that I have used for that.
<StackPanel.Resources>
<converters:BooleanToHiddenVisibility x:Key="boolToVis"/>
</StackPanel.Resources>
<ListBox ItemsSource="{Binding Items}" ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemContainerStyle="{StaticResource NullSelectionStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<VirtualizingStackPanel>
<ToggleButton Name="checkViewTextBox" >
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0">
<TextBlock Name="Text" Text="{Binding Title}" HorizontalAlignment="Center" MinWidth="30"/>
</Grid>
<Grid Grid.Row="0" Grid.Column="1">
<Image Source="C:\Work\Temp_Olotech\ToggleButton\ToggleButton\Tick_Mark_Dark-512.png" Height="20" Width="20"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Style>
</ToggleButton>
<ListBox ItemsSource="{Binding InnerItem}" Visibility="{Binding Path=IsChecked, ElementName=checkViewTextBox,
Converter={StaticResource boolToVis}}" ScrollViewer.VerticalScrollBarVisibility="Auto" Height="200">
<ListBox.ItemTemplate>
<DataTemplate>
<VirtualizingStackPanel CanVerticallyScroll="True">
<Expander Header="Title">
<VirtualizingStackPanel>
<TextBlock Text="{Binding Name}"></TextBlock>
</VirtualizingStackPanel>
</Expander>
</VirtualizingStackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</VirtualizingStackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox Text="only seen when above checkbox is checked"
Visibility="{Binding Path=IsChecked, ElementName=checkViewTextBox, Converter={StaticResource boolToVis}}"/>
</StackPanel>
</Grid>
Thank you for the help!

Data binding in DataTemplate of ListBox

I have a list box defined as below in xaml:
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Ellipse Visibility="{Binding IsSelected, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}" />
<ContentPresenter/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock x:Name="tb_Text" Text="{Binding IsSelected}"> </TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
I want to bind some property of tb_Text (say text property) to some property of the datacontext of the listbox (IsSelected property in this example). Is there a way to achieve that?
Note: IsSelected property is coming from the templated parent which has this listbox defined in it's Template.
Using ElementName and binding to the Visibility property of the Ellipse does the trick.

How to switch StackPanel items' Panel.ZIndex value with a Control outside?

Maybe this is a stupid asking, but I just wonder how to design this kind of layout:
first of all, I have a MenuList ObservableCollection. So I have to put these menus in to a stackPanel like this:
<Window.Resources>
<DataTemplate x:Key="MenuItemTemplate">
<Button Content="{Binding ContentText}" Panel.ZIndex="{Binding PIndex}" Padding="10" FontSize="20"/>
</DataTemplate>
</Window.Resources>
<ItemsControl ItemsSource="{Binding Menus}" ItemTemplate="{StaticResource MenuItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
so it looks like this:
after a while, there's a new bar under this menu added in:
<ItemsControl ItemsSource="{Binding Menus}" ItemTemplate="{StaticResource MenuItemTemplate}">
.......
</ItemsControl>
<Border Background="Green" VerticalAlignment="Top" Panel.ZIndex="10" Height="30" Margin="0,81,0,0"/>
Now it's look like this:
The requirment is, if a button selected, it should on the top of the bar, other unselected buttons should be covered by the bar:
But the buttons' are in a StackPanel, so they're all based on StackPanel's ZIndex.
My question is, how to design such layout in xaml?
I think using the renderTransform is better. No need to hard code PIndex in xaml. See below.
<DataTemplate x:Key="MenuItemTemplate">
<Button Content="{Binding}" Padding="10" FontSize="20" Height="30" Width="100">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1" ScaleY="1.2"></ScaleTransform>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
<Border Background="Green" VerticalAlignment="Top" Height="30" Margin="0,150,0,0"/>
<ItemsControl ItemsSource="{Binding Menus}" ItemTemplate="{StaticResource MenuItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Code behind:
public ObservableCollection<string> Menus { get; set; }
EDIT:
<DataTemplate x:Key="MenuItemTemplate">
<Button Content="{StaticResource image1}" Height="30" Width="100">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border x:Name="Border" Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}" Background="Orange">
</Border>
<ContentPresenter ContentSource="Content" HorizontalAlignment="Stretch" VerticalAlignment="Top"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="RenderTransform" TargetName="Border">
<Setter.Value>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1" ScaleY="1.2"></ScaleTransform>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DataTemplate>
If the bar is literally just a green bar, you can also put it on the DataTemplate as a separate Stackpanel from the button, and then put a Style.Trigger on the Button's stackpanel to increase the ZIndex OnMouseOver. The bar would look seamless even if it is just repeating.
So instead of:
<DataTemplate x:Key="MenuItemTemplate">
<Button Content="{Binding ContentText}" Panel.ZIndex="{Binding PIndex}" Padding="10" FontSize="20"/>
</DataTemplate>
You will have
<DataTemplate x:Key="MenuItemTemplate">
<Grid>
<StackPanel >
<StackPanel.Style>
<Style TargetType="StackPanel" >
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Panel.ZIndex" Value="3"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Panel.ZIndex" Value="1"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Button Width="100" Height="100" Content="{Binding ContentText}" Padding="10" FontSize="20" />
</StackPanel>
<StackPanel Panel.ZIndex="2">
<Border Background="Green" VerticalAlignment="Top" Height="30"/>
</StackPanel>
</Grid>
</DataTemplate>
(This doesn't look quite perfect if you run it, but you get the idea)
Dockpanel as our ItemPanelTemplate is the right choice.
Use a Grid with Button and Rectangle (for bottom border) as DataTemplate to show Menu items.
Don't apply margin in DataTemplate's Grid in step2 above. Instead use Grid Padding, Button margin for spacing.
DataTemplate :
<DataTemplate x:Key="MenuItemTemplate">
<Grid Background="DodgerBlue">
<Button Margin="5 5 5 0" HorizontalAlignment="Left" Panel.ZIndex="1" Content="{Binding ContentText}" Padding="1" Width="75" GotKeyboardFocus="Button_GotKeyboardFocus" LostKeyboardFocus="Button_LostKeyboardFocus"/>
<Rectangle Panel.ZIndex="2" Fill="BurlyWood" Height="5" Margin="0 25 0 0"/>
</Grid>
</DataTemplate>
ItemPanelTemplate :
<ItemsPanelTemplate>
<DockPanel Height="30" LastChildFill="True"/>
</ItemsPanelTemplate>
Use the below code as is :
<ItemsControl Panel.ZIndex="10" VerticalAlignment="Top" ItemsSource="{Binding Menus}" ItemTemplate="{DynamicResource MenuItemTemplate}" Margin="0">
<ItemsControl.Resources>
<DataTemplate x:Key="MenuItemTemplate">
<Grid Background="DodgerBlue">
<Button Margin="0" HorizontalAlignment="Left" Panel.ZIndex="1" Content="{Binding ContentText}" Padding="1" Width="75" GotKeyboardFocus="Button_GotKeyboardFocus" LostKeyboardFocus="Button_LostKeyboardFocus"/>
<Rectangle Panel.ZIndex="2" Fill="BurlyWood" Height="5" Margin="0 25 0 0"/>
</Grid>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<DockPanel Height="30" LastChildFill="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Code-Behind
public IList Menus { get; set; }
public Window1()
{
InitializeComponent();
Menus = new[] { new { ContentText = "Menu1" }, new { ContentText = "Menu2" }, new { ContentText = "Menu3" } };
this.DataContext = this;
}
private void Button_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
Panel.SetZIndex((Button)e.OriginalSource, 12);
}
private void Button_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
Panel.SetZIndex((Button)e.OriginalSource, 1);
}

Ability to click on a button as part of a background style WPF

I have a ListBox that sometimes contains no items. If this ListBox contains no items, then a watermark and a notification in the form of a button with a tool tip will be displayed. I originally had the button at the bottom right corner of my screen. But it was requested I move the button to a more central location, specifically just below the watermark in the ListBox. I moved the button to the background of the ListBox initially but that did not work because I was unable to get the tool tip or press the button. My question is: Is there a way to have the button function properly on the background of the ListBox.
Style:
<VisualBrush x:Key="WatermarkStyle" Stretch="None" AlignmentX="Center" AlignmentY="Center">
<VisualBrush.Visual>
<Grid>
<Button
Margin="0,50,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding ReloadCommand}"
ToolTip="{Binding Path=NotificationTip}"
Visibility="{Binding Path=ShowNotification,
Converter={StaticResource TrueToVisibleConverter}}"
Style="{StaticResource StaticStyle}"
IsEnabled="{Binding Path=CanReload}">
<Image Source="{Binding Path=NotificationIcon}" Stretch="Uniform" Width="35"/>
</Button>
<TextBlock FontFamily="SEGOEWP" FontSize="22" FontWeight="Normal" HorizontalAlignment="Center"
VerticalAlignment="Center" Foreground="Gray" Opacity="1" Text="{Binding BackgroundWatermark}"/>
</Grid>
</VisualBrush.Visual>
</VisualBrush>
ListBox:
<ListBox x:Name="ListBox"
Grid.Row="2"
Grid.ColumnSpan="3"
BorderThickness="1"
ItemsSource="{Binding Path=ListView}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{Binding SelectedDevice}"
SelectionMode="Single">
<ListBox.Style>
<Style TargetType="{x:Type ListBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding HasItems, RelativeSource={RelativeSource Self}}" Value="False">
<Setter Property="Background" Value="{StaticResource WatermarkStyle}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>

Excluding margin from ListBox item selection

I have a ListBox...
<ListBox Margin="10" ItemsSource="{Binding Employees}"
ItemTemplate="{DynamicResource EmployeesTemplate}"
HorizontalContentAlignment="Stretch" BorderThickness="0"
ScrollViewer.CanContentScroll="False"/>
...that has a custom DataTemplate:
<Window.Resources>
<DataTemplate x:Key="EmployeesTemplate">
<Border BorderThickness="1" BorderBrush="Black" SnapsToDevicePixels="True"
DockPanel.Dock="Top" Margin="0,0,0,5" Padding="5">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}" Padding="0,0,5,0"/>
<TextBlock Text="{Binding Path=LastName}"/>
</StackPanel>
<TextBlock Grid.Column="1" Text="{Binding Path=Title}"/>
</Grid>
<StackPanel>
<TextBlock Text="{Binding Path=DateOfBirth, StringFormat={}{0:MM/dd/yyyy}}"/>
<TextBlock Text="{Binding Path=Address}"/>
<TextBlock Text="{Binding Path=PhoneNumber}"/>
<TextBlock Text="{Binding Path=Salary, StringFormat={}{0:C}}"/>
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</Window.Resources>
When I select an item from the ListBox, the selection highlighting includes the 5-point Margin that is assigned to the bottom of each item (Border in DataTemplate):
You'll notice the similar situation on the left side, where the highlight overflows just a little bit. I did not notice that until now... hmm. So, I would like to restrict the selection highlight to the border area and nothing outside of it and be able to retain the margin spacing between the items.
How would I accomplish that? I tried manipulating Padding and Margin as much as I could, but I could not figure it out. Maybe I have to create a custom ListBox template?
I'm not sure if there is a simpler way but it works for me. I added a DataTemplate.Triggers section to my DataTemplate...
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}}, Path=IsMouseOver}" Value="True">
<Setter Property="Background" Value="LightBlue" TargetName="EmployeesTemplateBorder"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
<Setter Property="Background" Value="RoyalBlue" TargetName="EmployeesTemplateBorder"/>
</DataTrigger>
</DataTemplate.Triggers>
...and a ListBox.Resrouces section to the ListBox (to get rid of the default highlight behavior):
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
</ListBox.Resources>
Obviously, that doesn't do anything to the foreground, but that's not the concern right now, since that one is relatively easy comparing to this highlight routine.

Categories

Resources