I was looking a while for how to build a list item with a check mark if selected.
Checking different Resources, it seems there are a lot of code solutions, bot no true XAML only one.
So this is what i tried to achive:
Any additions are welcomed.
In the spirit of Answer-your-own (Stackoverflow blog)
So here is what I actually got after hours of figuring it out.
As said, any additions are welcomed.
The check mark is:
U+2714 (10004) ✔ HEAVY CHECK MARK Dingbats (2700–27BF)
The style code:
basically creating a wrapper for any item, setting base properties, and changing them on item selection, made available as StaticResource as checkmarkItem
<Window.Resources>
<Style x:Key="checkmarkItem" TargetType="ListBoxItem">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border" Background="Transparent" BorderThickness="5" BorderBrush="Transparent" Margin="0,1,0,1">
<Grid>
<TextBlock VerticalAlignment="Top" HorizontalAlignment="Right" Name="Marker" Visibility="Hidden" Background="#0078D7" Padding="5,0,0,5" Foreground="White">✔</TextBlock>
<ContentPresenter />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ListBoxItem.IsSelected" Value="true">
<Setter TargetName="Marker" Property="Visibility" Value="Visible" />
<Setter TargetName="Border" Property="BorderBrush" Value="#0078D7"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
The implementation:
it is just a regular stackpanel arrangement, all styles are added by referring in ItemContainerStyle="{StaticResource checkmarkItem}"
<Grid>
<Label Grid.Row="0" FontSize="26">Software</Label>
<ListView Grid.Row="1" SelectionMode="Multiple" BorderBrush="Transparent" ItemContainerStyle="{StaticResource checkmarkItem}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="64" AutomationProperties.Name="{Binding Title}">
<Image Source="{Binding Icon}" Height="48" Width="48" VerticalAlignment="Center" Margin="5,0,20,0"/>
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
<TextBlock Text="{Binding Title}" FontSize="16" TextWrapping="Wrap"/>
<TextBlock Text="{Binding Description}" TextWrapping="Wrap" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Related
I have a listview and padding must be 2 and color's getting system theme (using windows 8.1) but look very ugly.
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border Name="Border" Padding="2" SnapsToDevicePixels="True">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background" Value="{x:Static SystemParameters.WindowGlassBrush}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="IsSelected" Value="true"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
TIP: I used CornerRadius = 10 in DataTemplate.
<DataTemplate x:Key="DT">
<StackPanel Orientation="Vertical">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50*"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<Border Background="{Binding HEXRengi}" MinHeight="100" MinWidth="150" Height="100" Width="150" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.RowSpan="2" CornerRadius="10"/>
<ToggleButton x:Name="HEXRenkAl" Style="{DynamicResource DüzRenkPaletiDüğmeBiçimi}" Grid.Row="0" Click="HEXRenkAl_Click">
<Border Background="{Binding HEXRengi}" MinHeight="50" MinWidth="150" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="10">
<TextBox Text="{Binding HEXRengi}" Style="{DynamicResource SeçilebilirAmaYazılamazMetinKutusu}" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Justify" TextWrapping="Wrap" Foreground="White" FontFamily="Century Gothic" FontSize="16" FontWeight="Bold"/>
</Border>
</ToggleButton>
<ToggleButton x:Name="RGBRengiAl" Style="{DynamicResource DüzRenkPaletiDüğmeBiçimi}" Grid.Row="1" Click="RGBRengiAl_Click">
<Border Background="{Binding HEXRengi}" MinHeight="50" MinWidth="150" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="05">
<TextBox Text="{Binding RGBRengi}" Style="{DynamicResource SeçilebilirAmaYazılamazMetinKutusu}" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Justify" TextWrapping="Wrap" Foreground="White" FontFamily="Century Gothic" FontSize="16" FontWeight="Bold"/>
</Border>
</ToggleButton>
</Grid>
</StackPanel>
</DataTemplate>
Look like this;
And IsSelected;
When i used setter property opacity value apply all item. Just should apply on border, not all item.
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border" Property="Background" Value="{x:Static SystemParameters.WindowGlassBrush}"/>
<Setter TargetName="Border" Property="Opacity" Value=".5"/>
</Trigger>
How can i do it? Thanks for advices.
When i used setter property opacity value apply all item. Just should apply on border, not all item.
If you are wondering why opacity value is applying to all items, that is because you have named "Border" and you are targeting by name in your Trigger.
<Border Name="Border" Padding="2" SnapsToDevicePixels="True">
<ContentPresenter />
</Border>
I'm Trying to change listView GridView to IconView, as you see in the screenshot, each item is taking a row.
Style XAML
<UserControl.Resources>
<Style x:Key="FileItemStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="Width" Value="50"/>
<Setter Property="Margin" Value="5,5,5,5"/>
<Setter Property="Padding" Value="0,0,0,0"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" Width="50">
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="2.5"/>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ContentPresenter />
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
ListView XAML
<ListView ItemContainerStyle="{DynamicResource FileItemStyle}" HorizontalAlignment="Left" Height="194.667" Margin="11,77.666,0,0" VerticalAlignment="Top" Width="368.667" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True" UseLayoutRounding="False">
<ListView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Height="50">
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Stretch" Height="50" VerticalAlignment="Stretch" Width="50" CornerRadius="2.5"/>
<StackPanel>
<Image x:Name="Img" Source="BtnImg/Computer.png" Stretch="None" Margin="9,0,9,0" Width="32" Height="32"/>
<TextBlock x:Name="PCName" Margin="0" TextWrapping="Wrap" Height="18" HorizontalAlignment="Stretch" TextAlignment="Center"><Run Text="{Binding Content}"/></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<ListBoxItem Content="ddd"/> <!--**-->
<ListViewItem Content="zczxcz"/>
</ListView>
I've tried to use MDSN example : How to: Create a Custom View Mode for a ListView and modify it to get what I need, but it didn't work with me, I actually couldn't understand the example clearly, anyone can Simplify how can I create a View mode? Do I have to create an overrided ViewBase class?
Thanks in advance
Using the same exact Code Behind as My Answer to your previous question:
<Style x:Key="FileItemStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="Margin" Value="5,5,5,5"/>
<Setter Property="Padding" Value="0,0,0,0"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" >
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="2.5"/>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ContentPresenter/>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then:
<ListView ItemsSource="{Binding}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectedItem="{Binding SelectedComputer, RelativeSource={RelativeSource AncestorType=Window}}"
ItemContainerStyle="{StaticResource FileItemStyle}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel>
<TextBlock DockPanel.Dock="Bottom" Text="{Binding Name}"/>
<Rectangle Height="32" Width="32" Fill="Blue"/>
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Result:
Remove the hardcoded Width and Heights
Replace the blue rectangle for your Image.
Add some Triggers in the ControlTemplate so that you get highlighting when IsSelected="True"
Simply change the ItemsPanel of any ItemsControl in order to define how items are laid out.
Using a WrapPanel, you get a layout similar to Windows Explorer, where items are placed horizontally until there is no more horizontal space and then another "row" is created. Run the example and resize the Window to see this.
Bottom line: NO, you don't need custom code to customize the UI in WPF. It can be done with the existing controls and some XAML. Please read the "Alternatives to Writing a New Control" section in MSDN: Control Authoring Overview
I have ObservableCollection with items which I want to display in a ListBox.
Also I write a template for ListboxItem for correct display of my collection.
On this stage everything works fine.
in .cs
Sensors = new ObservableCollection<Sensor>();
...
lstBox.ItemsSource = Sensors;
in .xaml
...
<DataTemplate x:Key="SensorTileTemplate">
<Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Grid.Row="0" Grid.ColumnSpan="3"></TextBlock>
<Image Source="{Binding ImageModel.ImgSource}" Style="{StaticResource ImageGlowStyle}" Height="72" Grid.Row="1" Grid.Column="0"></Image>
<StackPanel Grid.Row="1" Grid.Column="1" Margin="5">
<TextBlock Text="IP:"></TextBlock>
<TextBlock Text="Port:"></TextBlock>
<TextBlock Text="Command port:"></TextBlock>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="2" Margin="5">
<TextBlock Text="{Binding DeviceAddress}"></TextBlock>
<TextBlock Text="{Binding DeviceDataPort}"></TextBlock>
<TextBlock Text="{Binding DeviceControlPort}"></TextBlock>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
<Style x:Key="ContainerStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="ListBoxItem.Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
...
<ListBox Name="lstBox" Focusable="False"
SelectionChanged="lstBox_SelectionChanged"
HorizontalContentAlignment="Stretch"
ItemTemplate="{StaticResource SensorTileTemplate}"
ItemContainerStyle="{StaticResource ContainerStyle}">
</ListBox>
The problem appears when I need to group certain items using expander as a group container.
in .cs
...
ICollectionView view = CollectionViewSource.GetDefaultView(Sensors);
view.GroupDescriptions.Add(new PropertyGroupDescription("GroupNumber"));
lstBox.ItemsSource = view;
...
in .xaml
<!--Same Template and Style-->
...
...
<Style x:Key="GroupContainerStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Group #" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
...
<ListBox Name="lstBox" Focusable="False"
SelectionChanged="lstBox_SelectionChanged"
HorizontalContentAlignment="Stretch"
ItemTemplate="{StaticResource SensorTileTemplate}"
ItemContainerStyle="{StaticResource ContainerStyle}">
<ListBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupContainerStyle}" />
</ListBox.GroupStyle>
</ListBox>
This code works and groups items but items become invisible.
So without grouping items display correctly but with grouping expanders show nothing in it.
I think there is something about ItemsPresenter in Expander but can't figure out what.
The problem was in one third party theme I use in my app. That theme has a ListBox template like:
<Style TargetType="{x:Type ListBox}">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Grid>
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2" Background="{DynamicResource ControlBackgroundBrush}" />
<ScrollViewer Margin="1" Style="{DynamicResource NuclearScrollViewer}" Focusable="false" Background="{x:Null}">
<StackPanel Margin="1,1,1,1" IsItemsHost="true" />
</ScrollViewer>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border" />
<Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So I use an ItemsPresenter instead of the StackPanel in that template and everything works now.
I need to set change background color for list item when mouse is over. Here is my code:
<DataTemplate x:Key="ListBoxSubCategoryListTemplate" DataType="{x:Type ListBoxItem}">
<StackPanel>
<Button x:Name="btnSubCategoryList" Template="{StaticResource subCategoryListItems}"
Content="{Binding Path=sub_category_name}"
Background="Transparent"
Height="25"/>
</StackPanel>
</DataTemplate>
<ControlTemplate x:Key="subCategoryListItems" TargetType="{x:Type Button}">
<StackPanel FlowDirection="LeftToRight" Orientation="Horizontal" >
<TextBlock Width="150"
Height="{TemplateBinding Button.Height}"
x:Name="textBlockSubCategoryName"
Background="{TemplateBinding Button.Background}"
Text="{TemplateBinding Button.Content}"
FontWeight="Bold" />
<Image x:Name="img" Width="15" Height="15" Source="/ExpressFurnitureSystem;component/Images/edit.png" ToolTip="Click to edit"></Image>
</StackPanel>
</ControlTemplate>
Please help...How??
How about a Trigger such as:
<DataTemplate x:Key="ListBoxSubCategoryListTemplate" DataType="{x:Type ListBoxItem}">
<StackPanel>
<Button x:Name="btnSubCategoryList" Template="{StaticResource subCategoryListItems}"
Content="{Binding Path=sub_category_name}"
Background="Transparent"
Height="25"/>
</StackPanel>
<DataTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="btnSubCategoryList" Property="Background" Value="Blue" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
I've got a data template for a list box item similar to the one on this page...
link
I would like to take it a step further and do something to highlight the items when they change. For example, using the code in the link above, I would like to put a trigger to do something when Widget.Quantity changes. Maybe make the quiantity item (nothing else) flash or something. How can I do that? I include the relevant code below...
<Window.Resources>
<Style x:Key="RoundedItem" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border CornerRadius="10" BorderBrush="Black" BorderThickness="1" Margin="1">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate DataType="{x:Type local:Widget}">
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Name}" />
<Label Content="{Binding Quantity}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding Widgets}" ItemContainerStyle="{StaticResource RoundedItem}" HorizontalContentAlignment="Stretch" />
Just add triggers to the DataTemplate.Triggers collection.
<DataTemplate DataType="{x:Type local:Widget}">
<StackPanel x:Name="panel" Orientation="Horizontal">
<Label Content="{Binding Name}" />
<Label Content="{Binding Quantity}" />
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding SomeProperty}" Value="True">
<Setter Property="Background" Value="Yellow" TargetName="panel" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
You'll probably want to add a property in your Widget class to do that. Or if Widget is a Model, you may want to wrap it in a WidgetViewModel class with an "IsFlashing" property on it. Then set the trigger to fire whenever this "IsFlashing" property is True.
I've managed to get it working with EventTriggers. Complete code below. In summary, the event trigger detects when the bound value changes, then turns the text orange briefly.
<UserControl.Resources>
<!-- instantiate an instance of the TimeSettingsCollection class -->
<c:TimeSettingsCollection x:Key="TimeSettingsCollection"/>
<Style x:Key="ListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="ItemBorder" BorderBrush="Gray" BorderThickness="1" Margin="3" Padding="7" Background="Transparent">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="ItemBorder" Property="Background" Value="LightBlue" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate DataType="{x:Type c:TimeSettingsItem}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Margin="0,0,8,0"
Style="{StaticResource smallTitleStyle}">Pc Name:</TextBlock>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=PcName}"
Style="{StaticResource textStyleTextBlock}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Margin="0,0,8,0"
Style="{StaticResource smallTitleStyle}">Time:</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=TimeSettings.DateTime, NotifyOnTargetUpdated=True}"
Style="{StaticResource textStyleTextBlock}" x:Name="timeTextBlock">
<TextBlock.Background>
<SolidColorBrush Color="Transparent"/>
</TextBlock.Background>
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="timeTextBlock"
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
To="Orange"
Duration="0:0:1"
AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
</Grid>
</DataTemplate>
</UserControl.Resources>
<DockPanel>
<ListBox Name="timeListBox" ItemsSource="{Binding Source={StaticResource TimeSettingsCollection}}" ItemContainerStyle="{StaticResource ListBoxItemStyle}" HorizontalContentAlignment="Stretch" IsSynchronizedWithCurrentItem="True">
</ListBox>
</DockPanel>