Thousands of radio buttons cause low performance in WPF - wpf

I need to create an user control that displays the wafer map, so I used a ListBox with uniform grid and each cell represents a die in the wafer. The problem I got is that when there are too many dies, for example, 100*100 uniformgrid, will be super slow to display, and also the scroller view is slow.
Below is my code:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid VirtualizingPanel.VirtualizationMode="Recycling" VirtualizingPanel.IsVirtualizing="True" x:Name="WaferMapGrid" Columns="{Binding MapColumnCount}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Rows="{Binding MapRowCount}" Background="AliceBlue" RenderTransformOrigin="0.5,0.5" Loaded="WaferMapGrid_Loaded">
<UniformGrid.LayoutTransform>
<ScaleTransform x:Name="WaferMapScaleForm" ScaleX="{Binding Path=Value, ElementName=ZoomSlider}" ScaleY="{Binding Path=Value, ElementName=ZoomSlider}" />
</UniformGrid.LayoutTransform>
</UniformGrid>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<ScrollViewer x:Name="WaferMapScrollViewer" CanContentScroll="True" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" Loaded="WaferMapScrollViewer_Loaded" ScrollChanged="OnScrollViewerScrollChanged" PreviewMouseDown="OnMouseLeftButtonDown" PreviewMouseWheel="WaferMapScrollViewer_PreviewMouseWheel" PreviewMouseMove="OnMouseMove" PreviewMouseUp="OnMouseLeftButtonUp" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" Padding="0">
<ScrollViewer.Resources>
<Style TargetType="ScrollBar">
<Style.Triggers>
<Trigger Property="Orientation" Value="Vertical">
<Setter Property="Width" Value="4"/>
<Setter Property="Margin" Value="0,0,0,0"/>
</Trigger>
</Style.Triggers>
</Style>
</ScrollViewer.Resources>
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<RadioButton x:Name="Die" MinHeight="{Binding ActualWidth,RelativeSource={RelativeSource Self}}" MinWidth="{Binding ActualHeight,RelativeSource={RelativeSource Self}}" Background="{Binding TestState,Converter={StaticResource TestStateConverter}}" BorderBrush="LightGray" BorderThickness="0.5" IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" GroupName="DieGroup" Style="{StaticResource DieStyle}" Margin="0" Content="{Binding DisplayText}" >
<RadioButton.ToolTip>
<local:DieInfo></local:DieInfo>
</RadioButton.ToolTip>
</RadioButton>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
By the way, the Virtualization seems not working in uniformgird. Any one knows how to optimize my code to improve the proformance? Attach the screen shot of my application:

Related

How to create a WPF ListBoxItem with check mark?

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>

Round close button in corner of image

I am creating gallery, it contains images. So I want to remove the images from gallery using close buttons. The position of the close button should be the corner of the every images. How can I create like this corner buttons styles? Any idea?
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Width="120">
<Button Height="25" VerticalAlignment="Top" Content="Show" Width="100" Margin="5" />
<Image Height="90" Source="{Binding Path=Thumbnail}" MouseLeftButtonDown="Image_MouseLeftButtonDown"/>
<TextBlock TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Text="{Binding Path=Name}" >
<TextBlock.ToolTip>
<ToolTip Visibility="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget, Converter={StaticResource trimmedVisibilityConverter}}">
<ToolTip.Content>
<TextBlock Text="{Binding Name}"/>
</ToolTip.Content>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
</StackPanel>
<!--<Separator Width="5" Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" Background="Transparent"/>-->
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
place Image and Button in the same Grid. Align button to top right corner, and add margin to top and right sides of image, so the button goes outside image borders
<Grid>
<Image Margin="0,8,8,0"/>
<Button HorizontalAlignment="Right" VerticalAlignment="Top"
Width="16" Height="16" Content="x"/>
</Grid>
Here's a round button from one of my samples which looks pretty similar to what you're after.
The colours and mouseover may be different.
<SolidColorBrush x:Key="DarkLight" Color="Chocolate"/>
<SolidColorBrush x:Key="BrightMid" Color="PapayaWhip"/>
<Geometry x:Key="CloseIcon">
M19.85228,12.08996L12.093,19.849201 24.242323,31.997846 12.094,44.145998 19.852051,51.904958 32.001186,39.756277 44.150543,51.904958 51.909,44.145994 39.760246,31.997501 51.909,19.849201 44.15049,12.08996 32.001431,24.238849z M32,0C49.671021,3.1599484E-07 64,14.329407 64,31.998501 64,49.677606 49.671021,63.997003 32,63.997003 14.328003,63.997003 0,49.677606 0,31.998501 0,14.329407 14.328003,3.1599484E-07 32,0z
</Geometry>
<Style x:Key="CloseButton" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="{StaticResource BrightMid}"/>
<Setter Property="Background" Value="{StaticResource DarkLight}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
<Border CornerRadius="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}"
Width="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}"
Name="border"
BorderThickness="1"
BorderBrush="Black"
Background="{Binding Background, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}"
>
<Path Data="{StaticResource CloseIcon}" Stretch="Fill"
Fill="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}"
/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WidthConverter is not trigger when GroupBox has been resize

GroupBox has an auto column width. I can't think anymore why WidthConverter is not triggered when GroupBox has been resized. Any alternatives?
The goal is to display 5 rows and 5 columns always. When user resized the window, the column width must also resized. TIA!
<GroupBox Grid.Column="0" Grid.ColumnSpan="7" Grid.Row="10" x:Name="GbSerial"
Template="{StaticResource GbSerialProgrammed}">
<GroupBox.Header>
<TextBlock TextDecorations="Underline" FontWeight="Bold" FontSize="24" HorizontalAlignment="Center" TextAlignment="Center"
Text="{lgg:Lgg Path=AllSerialNumberProgrammed}"/>
</GroupBox.Header>
<ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
<ItemsControl x:Name="IcSerialNumbers" Background="White" Tag="{Binding ElementName=GbSerial, Path=ActualWidth}"
ItemsSource="{Binding AllSerialNumberProgrammed, UpdateSourceTrigger=PropertyChanged}"
helper:ItemsControlHelper.ScrollToLastItem="True"
FontSize="24" Height="250" >
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Height" Value="50"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Width" Value="{Binding ElementName=GbSerial,
Path=ActualWidth, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True,
Mode=OneTime, Converter={StaticResource WidthConverter},
ConverterParameter=5}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" FlowDirection="LeftToRight" Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl >
</ScrollViewer>
</GroupBox>
Mode OneTime, as name implies, means it is invoked only once when it starts off.

Relative Binding in RichTextBox to its Paragraph

I want to display a Line of Text via an ItemsControl beside a RichTextBox. Therefore I created this ControlTemplate:
<RichTextBox Margin="5,0,5,0">
<RichTextBox.Resources>
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="5,0,5,0"/>
<Setter Property="LineHeight" Value="30"/>
<Setter Property="LineStackingStrategy" Value="BlockLineHeight"/>
</Style>
</RichTextBox.Resources>
<RichTextBox.Template>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<ItemsControl ItemsSource="{Binding Lines}" Margin="5,0,5,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton Content="{Binding}" Height="{Binding BIND_ME_TO_LineHeigh_OF_PARAGRAPH" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Border Name="Border" CornerRadius="2" Padding="2" Background="White" BorderBrush="Black" BorderThickness="0" >
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Border>
</StackPanel>
</ControlTemplate>
</RichTextBox.Template>
To make the Items in the ItemsControl the same size as the paragraph's line I want to bind the ToggleButton's height to the LineHeight of the Paragraph which I defined in the Style for the Pararaph ( ). How can I do that?
Thanks

WPF Navigation Page Breadcrumb

I found code to use a breadcrumb instead of the navigation buttons for my pages. This code works perfect with setting a page as the startup. My problem is that I need to have a window with a frame control as the startup and this is causing the breadcrumb to not show at all. I seem to be missing something with my styling. The types used to be NavigationWindow but I changed them to Frame to try and get a working solution.
<Style TargetType="Frame" x:Key="{x:Type Frame}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Frame">
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ItemsControl ItemsSource="{Binding
RelativeSource={RelativeSource AncestorType={x:Type Frame}},
Path=BackStack}">
<!--Force the ItemsContol to use a wrap panel as Items host-->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<local:InverseWrapPanel KeyboardNavigation.TabNavigation="Cycle"
KeyboardNavigation.DirectionalNavigation="Cycle"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="NavigationCommands.NavigateJournal"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Content="{Binding Name}">
<Button.Template>
<ControlTemplate TargetType="Button">
<WrapPanel>
<TextBlock Name="text1" FontWeight="Bold" Text="{TemplateBinding Content}"/>
<TextBlock Name="text2" FontWeight="Bold" Text=">>" Margin="2,0,0,0"/>
</WrapPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="text1" Property="Foreground" Value="Blue"/>
<Setter TargetName="text2" Property="Foreground" Value="Blue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<AdornerDecorator Grid.Row="2">
<ContentPresenter Name="PART_NavWinCP" ClipToBounds="true"/>
</AdornerDecorator>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Change:
<ItemsControl ItemsSource="{Binding
RelativeSource={RelativeSource AncestorType={x:Type Frame}},
Path=BackStack}">
to:
<ItemsControl ItemsSource="{Binding
RelativeSource={RelativeSource TemplatedParent},
Path=BackStack}">
and its should work.

Resources