WPF - 300+ buttons on UI - really slow... what's the alternative? - c#

I've got about 300+ buttons that are represented in a grid. When I try to render this, it takes a good 5 seconds to load up all buttons. Is there any alternative? Functionality that already exists such as hover over, mouse enter, left button click etc are all needed... just wondering if there is a way to speed up button rendering.
Buttons are created dynamically in a grid, with an ItemsControl, that contains an ItemsPanelTemplate (that is just a grid definition of width and height), a DataTemplate in ItemsControl.Resources, where the ToggleButton(s) that are created dynamically (300+) are created.
The datatemplate in the ItemsControl.Resources looks like this:
<DataTemplate DataType="{x:Type engine:Weodel}">
<ToggleButton
Tag="{Binding}"
IsChecked="{Binding IsSelected}"
Height="{Binding ElementName=weItemControl,
Path=DataContext.ButtonHeightWidth}"
Width="{Binding ElementName=weItemControl,
Path=DataContext.ButtonHeightWidth}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="{Binding ElementName=weItemControl,
Path=DataContext.ButtonMarginToUse}"
Padding="2"
Style="{StaticResource WeButton}">
</ToggleButton>
</DataTemplate>
The style of the button in resource dictionary:
<Style TargetType="{x:Type ToggleButton}" x:Key="WeButton">
<Setter Property="Background" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Ellipse Fill="{TemplateBinding Background}" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" TextBlock.TextAlignment="Center">
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextAlignment" Value="Center"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" Value="{Binding GColour}"/>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Background" Value="{Binding GColour}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Related

How to change the style of a button when pressed

I am trying to change the style of a button when I click on it while the app is running.
Like I have a button with a grey color, I want it to change to red when I click on it?
I tried to do it with the Click event, however the button still shows the default effect when I hover over the button.
Here is the WPF code I used.
<Style TargetType="Button" x:Key="btnExitDef">
<Setter Property="Background" Value="#FF1E1E1E"/>
<Setter Property="Foreground" Value="#FFD6D6D6"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="0"
BorderThickness="0"
Padding="0"
BorderBrush="#000">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center">
</ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="#fff"/>
</Trigger>
</Style.Triggers>
</Style>
<Button Height="35" Width="45" Name="btnExit" Content="✕" BorderBrush="{x:Null}" Click="btnExit_Click" Style="{StaticResource btnExitDef}"/>
You just need to edit the button's style and add another Trigger for the IsPressed property.
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>

WPF: Move focus to previous control (SHIFT + Tab) when using ControlTemplate with Placeholder Textbox

I created a WPF TextBox with Placeholder text by creating a customized Style that overlays one TextBox (as a placholder text) on another TextBox in the ControlTemplate.
Here's the Style definition:
<Style x:Key="TextBoxFormBaseStyle"
BasedOn="{StaticResource {x:Type TextBox}}"
TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<TextBox x:Name="_textSource"
Panel.ZIndex="2"
Background="Transparent"
Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name="_textTag"
Panel.ZIndex="1"
Focusable="False"
Text="{TemplateBinding Tag}">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, Source={x:Reference _textSource}}" Value="">
<Setter Property="Foreground" Value="{Binding Path=OpacityMask, Source={x:Reference _textSource}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
<!-- Move Focus to child control -->
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="_textSource" Property="FocusManager.FocusedElement" Value="{Binding ElementName=_textSource}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
A Trigger on Property IsFocused allows focusing the the child TextBox control (named _textSource) when navigating through multiple TextBox's by Tab key.
Navigating to the previous element by pressing SHIFT + Tab is not working. How can I get SHIFT + Tab to set the focus to the previous element?
There are better ways to add a watermark if you want the TextBox to actuallty behave and get focused like a built-in TextBox. Try this style:
<Style x:Key="TextBoxFormBaseStyle" BasedOn="{StaticResource {x:Type TextBox}}" TargetType="{x:Type TextBox}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid>
<TextBox x:Name="_textTag"
Focusable="False"
Text="{TemplateBinding Tag}"
BorderThickness="0">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, RelativeSource={RelativeSource AncestorType=TextBox}}" Value="">
<Setter Property="Foreground" Value="{Binding Path=OpacityMask, RelativeSource={RelativeSource AncestorType=TextBox}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Sample usage:
<TextBox OpacityMask="Red" Tag="Red Watermark" Text="text" Style="{StaticResource TextBoxFormBaseStyle}" />
<TextBox OpacityMask="Green" Tag="Green Watermark" Text="text" Style="{StaticResource TextBoxFormBaseStyle}" />

Remove Listview mouse over

I have a simple list view.
<ListView x:Name="DatabasesLstVw" ItemsSource="{Binding Path=Issues}"
ItemContainerStyle="{StaticResource removeMouseOverStyle}"
AlternationCount="2" Grid.Row="1" Margin="20,10,20,0"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
FontSize="12" FontWeight="Normal"
BorderThickness="0" Background="Transparent"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.Resources>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Visibility" Value="Collapsed" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView >
<GridViewColumn Header="Message">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Text="{Binding Name}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I have created a style trying to remove the default mouse over and select styling.
<Style x:Key="removeMouseOverStyle" TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Transparent"></Setter>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Margin" Value="0,0,0,0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="FontSize" Value="12"/>
</Trigger>
<Trigger Property="ItemsControl.IsMouseOver" Value="true">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontWeight" Value="Normal"/>
</Trigger>
</Style.Triggers>
</Style>
I cant post what its doing without trying to create a gif picture of it. Basically its hopping a little with the mouse over. First I thought it was setting margin , then tried padding and font size.
What exactly is this default mouse over doing and how do I remove it?
There could be many ways how they could have implemented selection\mouse over. For example often it is done by showing separate Border for every state. For control such simple as ListViewItem it's better to override it's ControlTemplate and do what you need there. You can use default control template, just remove triggers:
<Style x:Key="removeMouseOverStyle"
TargetType="ListViewItem">
<Setter Property="SnapsToDevicePixels"
Value="true" />
<Setter Property="OverridesDefaultStyle"
Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="Border"
Padding="2"
SnapsToDevicePixels="true"
Background="Transparent">
<GridViewRowPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
With this style items won't change their appearence on selection or mouse over. Also, you can use base ItemsControl control - it does not have selection\mouse over behavior by default.

ToggleButton Trigger IsChecked Doesn't Change Background

I have a ToggleButton with a red background. I need to set a green background when the toggle button is checked.
I've tried this:
<ToggleButton Content="Test 001" Name="btn03" Height="20">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Background" Value="#ff0000" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="#00ff00" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
But instead a green color I get a light blue color (I think is the default color of my
system).
What I'm doing wrong and how to fix it?
WPF 4.0 doesen't allow this. Look here for a different approach:
<Grid>
<Grid.Resources>
<Style x:Key="ToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="border" Background="Red">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" TargetName="border" Value="Green"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<ToggleButton Content="ToggleButton" Style="{StaticResource ToggleButtonStyle}"/>
</Grid>

Use a ContentPresenter for personnalize a template

I created a ressourceDictionnary for creating a templateButton.
I would like to be able to change the png image when i use this template, i think i need to use a ContentPresenter, but i don't know why.
Here is my RessourceDictionnary :
<ControlTemplate TargetType="{x:Type Button}" x:Key="BoutonRessources">
<Button Width="32" Margin="0,0,7,0" Name="tbrClear" ToolTip="Clear" VerticalAlignment="Center" BorderThickness="0" HorizontalAlignment="Center" Background="Transparent" HorizontalContentAlignment="Center">
<Border>
<Image Source="xRtDiva_XWPF_TBR_PREMIER.PNG_IMAGES.png" Height="18"/>
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="BoutonToolbarSelected.png"/>
</Setter.Value>
</Setter>
<Setter Property="Height" Value="22"/>
<Setter Property="Width" Value="32"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
</Button>
So, when i use this Button template, i would like to be able to pass them an other png image to display. For example i would like to replace xRtDiva_XWPF_TBR_PREMIER.PNG_IMAGES.png by MyPicture.png.
How doing this ? With a contentPresenter ?
Thanks :)

Categories

Resources