How to set a ToolTip for each ListBoxItem - wpf

I have a ListBox control; how would I set the ToolTip for each ListBoxItem using the code below.
<ListBox Name="FillSelections"
VerticalContentAlignment="Stretch"
Margin="1, 3, 1, 3"
IsEnabled="True"
Grid.Column="0"
Background="Transparent"
HorizontalContentAlignment="Center"
SelectedItem="{Binding SelectedColor}"
SelectionMode="Single"
Style="{StaticResource HorizontalListBoxStyle}"
ItemsSource="{Binding FillColors}"
ItemTemplate="{StaticResource ColorsItemTemplate}">
</ListBox>
<DataTemplate x:Key="ColorsItemTemplate">
<Border Width="20"
Height="16"
BorderBrush="Black"
BorderThickness="1">
<Border.Background>
<SolidColorBrush Color="{Binding}" />
</Border.Background>
<Path Stroke="Red"
StrokeThickness="3"
x:Name="abc"
Visibility="Hidden">
<Path.Data>
<LineGeometry StartPoint="0,16" EndPoint="20,0"/>
</Path.Data>
</Path>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding}" Value="#00FFFFFF">
<Setter TargetName="abc" Property="Visibility" Value="Visible"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>

Try something like this
<ListBox Width="400" Margin="10"
ItemsSource="{Binding Source={StaticResource myTodoList}}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=TaskName}"
ToolTipService.ToolTip="{Binding Path=TheTooltipText}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Of course adapt the ItemsSource binding with whatever your binding source is, and the binding Path parts with whatever public property of the objects in the list you actually want to display.

You could create a style for ListBoxItem. So something along the lines of:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip>
<TextBlock>Hello</TextBlock>
</ToolTip>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListBox>
<ListBoxItem>
<TextBlock Text="Hello" />
</ListBoxItem>
</ListBox>
</Grid>
</Window>

Related

Display Button as long as ListView doesn't has more than five Items

I have some ListViews who each can contain max 5 ListViewItems. As long as there are less than 5 items there should be an Button be displayed. I have already written an Value Converter that returns true if the Count is less than five. But now I have Problems styling my ListView. Because i.e. if there are three ListViewItems they should be styled with the normal style and the "4" item should be an Button. My tought was that I add a new ListViewItem inside the DataTrigger. Is that possible or is there a better way to achive that?
Style.xaml
<Style TargetType="{x:Type ListView}">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<UniformGrid Rows="5" Columns="1"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Items.Count, Converter={StaticResource ItemCounterConverter}}" Value="true">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock>No items to display</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<!--ListViewItem-->
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border BorderBrush="#5076A7" BorderThickness="1">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#FFFFFF" Offset="0.0"/>
<GradientStop Color="#C0D3EA" Offset="1.0"/>
</LinearGradientBrush>
</Border.Background>
<StackPanel TextElement.FontFamily="Segoe UI" TextElement.FontSize="12">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="15"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Padding="3,0,0,0" Text="{Binding Betreff}" TextTrimming="CharacterEllipsis" Grid.Column="0" Grid.Row="0"/>
<Button FontSize="7" Content="X" Grid.Column="1" Grid.Row="0"/>
</Grid>
<TextBlock Padding="3,0,0,0" Text="{Binding Kunde}"/>
<StackPanel Orientation="Horizontal">
<TextBlock FontWeight="Bold" Padding="3,0,0,0" Text="{Binding Ort}"/>
<TextBlock Padding="3,0,0,0" Text="("/>
<TextBlock Text="{Binding Alternative}"/>
<TextBlock Text=")"/>
</StackPanel>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Update
Thanks this looks very promising and you understood it right. But I have problems implementing it. Every ListView has a differnt ItemSource(they're all ObservableCollections), so I don't know if I can set the ItemSource inside the Style? But the Button at the End should be available to all of them. My Styles are in a different File than the ListViews themselves. The definition for my ListViews looks like this:
AppointmentOverview.xaml
<ListView Grid.Column="1" Grid.Row="3" ItemsSource="{Binding Mov}"/>
<ListView Grid.Column="1" Grid.Row="4" ItemsSource="{Binding Mon}"/>
<ListView Grid.Column="2" Grid.Row="3" ItemsSource="{Binding Div}"/>
<ListView Grid.Column="2" Grid.Row="4" ItemsSource="{Binding Div}"/>
<ListView Grid.Column="3" Grid.Row="3" ItemsSource="{Binding Miv}"/>
<ListView Grid.Column="3" Grid.Row="4" ItemsSource="{Binding Min}"/>
<ListView Grid.Column="4" Grid.Row="3" ItemsSource="{Binding Dov}"/>
<ListView Grid.Column="4" Grid.Row="4" ItemsSource="{Binding Don}"/>
<ListView Grid.Column="5" Grid.Row="3" ItemsSource="{Binding Frv}"/>
<ListView Grid.Column="5" Grid.Row="4" ItemsSource="{Binding Frn}"/>

ListView DataTemplate, ControlTemplate and Style

Still learning WPF....thanks for any help.
Is there any way to Refactor this:
<ListBox Name="lbEvents"
VerticalAlignment="Stretch"
SelectionMode="Multiple"
Loaded="lbCenterEvents_Loaded"
HorizontalAlignment="Stretch"
BorderBrush="Transparent"
Background="Transparent"
SelectionChanged="lbCenterEvents_SelectionChanged"
ItemContainerStyle="{StaticResource KioskCheckboxListItemContainer}">
<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>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Grid.Column="0"
Margin="0,10,0,0"
Padding="5,30,5,10"
DockPanel.Dock="Top"
Style="{StaticResource KioskCheckBox}"
Background="{StaticResource brshSecondaryColor}"
FontSize="26"
HorizontalAlignment="Stretch"
IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"
Content="{Binding DisplayDescriptionForKiosk}">
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Into something like this:
<ListBox Name="lbEvents" Style="{StaticResource MyFinalListBox}"
VerticalAlignment="Stretch"
SelectionMode="Multiple"
Loaded="lbCenterEvents_Loaded"
HorizontalAlignment="Stretch"
BorderBrush="Transparent"
Background="Transparent" />
Just trying to get an idea...I shouldn't need exact code, pseudo code should be sufficient (I hope), thanks in advance.
EDIT: I'm asking this because I'm trying to find a way to do this with the least amount of references to StaticResources. I realize I can pull out the templates and styles, but I am hoping some one can show me how reduce it to one StaticResource.
Yes you want (something like)
<UserControl>
<UserControl.Resources>
<DataTemplate x:Key="MyItemTemplate" DataType="{x:Type MyDataType}">
<CheckBox Grid.Column="0"
Margin="0,10,0,0"
Padding="5,30,5,10"
DockPanel.Dock="Top"
Style="{StaticResource KioskCheckBox}"
Background="{StaticResource brshSecondaryColor}"
FontSize="26"
HorizontalAlignment="Stretch"
IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"
Content="{Binding DisplayDescriptionForKiosk}">
</CheckBox>
</DataTemplate>
<Style x:Key="MyFinalListBox" TargetType="{x:Type ListBox}">
<Setter Property="SelectionMode" Value="Multiple" />
... put more properties here
</Style>
</UserControl.Resources>
</UserControl>
<ListBox Name="lbEvents"
ItemTemplate="{StaticResource MyItemTemplate}"
Style="{StaticResource MyFinalListBox}"
VerticalAlignment="Stretch"
Loaded="lbCenterEvents_Loaded"
HorizontalAlignment="Stretch"
BorderBrush="Transparent"
Background="Transparent" />

WPF: Groupstyle not working correctly because of Style and/or modified ListBox

I am trying to use a GroupStyle but instead of showing the groupname as a header over the items in the list it only shows the header and not the items.
It works fine until I applied a special style to the list. I then decided this style was pretty bogus so I created a UserControl fro this effect. The problem persists.
The purpose of the UserControl is to have a expending effect on the selected item where normally it could show some info and then more info when expanded.
UserControl:
<UserControl x:Class="MyProject.CustomUC.ExpandingList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<ListBox x:Name="List"
ItemsSource="{Binding Path=Collection}">
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<Border BorderBrush="Blue"
BorderThickness="1"
CornerRadius="2"
Background="White">
<ScrollViewer Focusable="False">
<StackPanel Margin="2" IsItemsHost="True" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ListBox.Template>
<ListBox.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Margin="4" Name="Border" BorderBrush="Blue" BorderThickness="1" CornerRadius="5" Background="LightBlue">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ContentPresenter Name="Head"
Margin="4"
Visibility="Visible"
ContentTemplate="{Binding ElementName=List, Path=DataContext.HeadTemplate}"/>
<Border Name="Tail" Visibility="Collapsed" Grid.Row="1" BorderThickness="0,1,0,0" BorderBrush="Blue">
<ContentPresenter Margin="4"
ContentTemplate="{Binding ElementName=List, Path=DataContext.TailTemplate}" />
</Border>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Tail" Property="Visibility" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid>
</UserControl>
Using the UserControl:
<CustomUC:ExpandingList Collection="{Binding Path=List}">
<CustomUC:ExpandingList.HeadTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=DisplayName}" />
</DataTemplate>
</CustomUC:ExpandingList.HeadTemplate>
<CustomUC:ExpandingList.TailTemplate>
<DataTemplate DataType="{x:Type ViewModel:ElementViewModel}">
<TextBlock Text="{Binding Path=SomeOtherProperties}" />
</DataTemplate>
</CustomUC:ExpandingList.TailTemplate>
</CustomUC:ExpandingList>
This works if I change from the ExpandingList UserCotnrol:
<ListView ItemsSource="{Binding Path=List}" >
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=DisplayName}" />
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
Anyone know what could be wrong?
In the ListBox template, replace:
<StackPanel Margin="2" IsItemsHost="True" />
with
<ItemsPresenter Margin="2" />
The ItemsPresenter class has extra logic for groups, that you lose if you're directly using a panel to display the items.

CollectionViewSource+PropertyGroupDescription - count of items in a group

In my WPF application I have a CollectionViewSource which is providing a view to a private ObservableCollection. The CollectionViewSource has a PropertyGroupDescription which is utilised in a ListBox to present data to the User's preference.
Using a ControlTemplate containing a Expander Control within the ListBox GroupStyle, the result is quite nice. However, I would like to show the number of items in each group in the Expander Header in addition to the Group Name. Any ideas on the binding path?
Regards,
Liam
<Style x:Key="basicGroupStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander Header="{Binding Name}" IsExpanded="True">
<ItemsPresenter/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ListBox ItemsSource="{Binding Source={StaticResource myViewSource}}">
<ListBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource basicGroupStyle}"/>
</ListBox.GroupStyle>
</ListBox>
you have to use property ItemCount
<Window x:Class="WpfApplication11.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<XmlDataProvider x:Key="data">
<x:XData>
<Animals xmlns="">
<Animal name="Dory" Species="Fish" />
<Animal name="Felix" Species="Cat" />
<Animal name="Fluffy" Species="Dog" />
<Animal name="Jake" Species="Snake" />
<Animal name="Mittens" Species="Cat" />
<Animal name="Murtle" Species="Turtle" />
<Animal name="Nemo" Species="Fish" />
<Animal name="Rex" Species="Dog" />
<Animal name="Rover" Species="Dog" />
<Animal name="Toonces" Species="Cat" />
</Animals>
</x:XData>
</XmlDataProvider>
<CollectionViewSource x:Key="animalsBySpecies" Source="{Binding Source={StaticResource data}, XPath=Animals/Animal}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="#Species" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<DockPanel>
<ScrollViewer DockPanel.Dock="Bottom" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Source={StaticResource animalsBySpecies}}">
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<GroupBox >
<GroupBox.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text ="{Binding Name}" ></TextBlock>
<TextBlock Text="(" Grid.Column="1" Margin="15,0,0,0"></TextBlock>
<TextBlock Text="{Binding ItemCount}" Grid.Column="1" Margin="20,0,0,0"
HorizontalAlignment="Right" ></TextBlock>
<TextBlock Text=")" Margin="0,0,-5,0" Grid.Column="1
HorizontalAlignment="Right" ></TextBlock>
</Grid>
</GroupBox.Header>
<ItemsPresenter />
</GroupBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ItemsControl.GroupStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding XPath=#name}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</Window>
I updated the Group Style as follows. I found that I could not use a MultiBinding in the Expander.Header property, nothing was displayed on screen, I needed to include an intermediate TextBlock instead.
<Style x:Key="basicGroupStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} ({1})">
<Binding Path="Name"/>
<Binding Path="ItemCount"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Expander.Header>
<ItemsPresenter/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

How to implement a XAML Radio Button control with an ObservableCollection source?

I have the following ComboBox element in XAML:
<ComboBox ItemsSource="{Binding CollectionControlValues}"
SelectedItem="{Binding CollectionControlSelectedValue, UpdateSourceTrigger=PropertyChanged}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
I would like to implement RadioButtons in the same way, like this:
PSEUDO-CODE:
<RadioButtons ItemsSource="{Binding CollectionControlValues}"
SelectedItem="{Binding CollectionControlSelectedValue, UpdateSourceTrigger=PropertyChanged}">
<RadioButtons .ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value}" />
</DataTemplate>
</RadioButtons .ItemTemplate>
</RadioButtons >
However, the only WPF RadioButton implementations I can find are static like this.
<StackPanel x:Name="rbHolder1" Style="{StaticResource rbStackPanelStyle}">
<RadioButton Style="{StaticResource rbStyle}">RadioButton 1</RadioButton>
<RadioButton Style="{StaticResource rbStyle}">RadioButton 2</RadioButton>
<RadioButton Style="{StaticResource rbStyle}">RadioButton 3</RadioButton>
<RadioButton Style="{StaticResource rbStyle}">...</RadioButton>
</StackPanel>
How can I create a RadioButton control which is not static like the above but instead gets its data from its ItemsSource property as in the above ComboBox example?
Use ItemsControl and DataTemplate:
<ItemsControl ItemsSource="{Binding CollectionControlValues}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding Value}" IsChecked="{Binding SomeProperty}" GroupName="name"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
code in window1.xaml file
<Window x="RadioButton.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local ="clr-namespace:RadioButton"
Title="Window1" Height="300" Width="300" Loaded="Window_Loaded">
<StackPanel>
<StackPanel.Resources>
<ObjectDataProvider x:Key="RadioOptions" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:RadioOption" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<Style x:Key="RadioButtonList" TargetType="{x:Type ListBox}">
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="Margin" Value="2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border Background="Transparent">
<RadioButton Focusable="False"
IsHitTestVisible="False"
IsChecked="{TemplateBinding IsSelected}">
<ContentPresenter />
</RadioButton>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<ListBox Margin="37,20,28,58" Name="listBox1" Style="{StaticResource RadioButtonList}" ItemsSource="{Binding Source={StaticResource RadioOptions}}" />
</StackPanel>
this line
<ListBox` Margin="37,20,28,58" Name="listBox1" Style="{StaticResource RadioButtonList}"
ItemsSource="{Binding Source={StaticResource RadioOptions}}"
is using itemsource property
C# code
namespace RadioButton
{
public enum RadioOption
{
option1,
option2,
option3,
option4
}
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}
i think this will help you out..

Resources