I am developing a UWP application which has a view which renders number of products in a GridView, I have created a data template for each product to render, below is the attached XAML code.
When I ran Visual Studio Profiler to debug the time taken in rendering of the layout, I found that under Layout section each Product template's ListViewItemPresenter was taking around 6-7 ms to render, so if I am having 10 products in the GridView it adds 70ms for rendering which ultimately makes the UI slow, I have loader in the view which displays when UI is being rendered but I want this time to be reduced.
Can anyone help?
Any help would be highly appreciated.
<UserControl.Resources>
<converters:ProductQuantityVisibilityConverter x:Key="ProductQuantityVisibilityConverter" />
<!--<converters:DoubleDigitVisibilityConverter x:Key="DoubleDigitVisibilityConverter" />
<converters:TripleDigitVisibilityConveter x:Key="TripleDigitVisibilityConveter" />
<converters:FourDigitVisibilityConverter x:Key="FourDigitVisibilityConverter" />-->
<Style TargetType="Button"
BasedOn="{StaticResource ButtonWithNoBorder}"
x:Name="QuantityButtonStyle">
<Setter Property="Background"
Value="White" />
<Setter Property="HorizontalAlignment"
Value="Stretch" />
<Setter Property="HorizontalContentAlignment"
Value="Left" />
<Setter Property="Padding"
Value="2,0" />
<Setter Property="Foreground"
Value="{StaticResource CancelButtonForeGround}" />
<Setter Property="FontFamily"
Value="Segoe UI Light" />
<Setter Property="FontWeight"
Value="Light" />
<Setter Property="VerticalAlignment"
Value="Stretch" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
</Style>
</UserControl.Resources>
<Grid Background="White">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<trigger:EqualsStateTrigger Value="{x:Bind ProductDetails.FontSizeSelector, Mode=OneWay}"
EqualTo="1" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="txtQuantity.FontSize"
Value="57" />
</VisualState.Setters>
</VisualState>
<VisualState>
<VisualState.StateTriggers>
<trigger:EqualsStateTrigger Value="{x:Bind ProductDetails.FontSizeSelector, Mode=OneWay}"
EqualTo="2" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="txtQuantity.FontSize"
Value="47" />
</VisualState.Setters>
</VisualState>
<VisualState>
<VisualState.StateTriggers>
<trigger:EqualsStateTrigger Value="{x:Bind ProductDetails.FontSizeSelector, Mode=OneWay}"
EqualTo="3" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="txtQuantity.FontSize"
Value="33" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid>
<!--#region When Quantity is zero-->
<Grid x:Name="productWithZeroQuantity"
Padding="0">
<Button x:Name="btnProductImage"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Padding="0"
Style="{StaticResource ButtonWithNoBorder}"
Command="{x:Bind IncreaseQuantityCommand,Mode=OneWay}"
CommandParameter="{x:Bind ProductDetails.StockCode, Mode=OneWay}"
Height="60"
Width="120">
<Button.Background>
<ImageBrush Stretch="Fill"
ImageSource="{x:Bind ProductDetails.ImageSource, Mode=OneWay}" />
</Button.Background>
<Rectangle Width="{Binding ActualWidth, ElementName=btnProductImage}"
Height="{Binding ActualHeight, ElementName=btnProductImage}"
Margin="0">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<GradientStop Offset="0.728"
Color="#50FFFFFF" />
<GradientStop Offset="1"
Color="#FFF9F1F1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<i:Interaction.Behaviors>
<ic:EventTriggerBehavior EventName="Holding">
<ic:InvokeCommandAction Command="{x:Bind SetQuantityCommand, Mode=OneWay}"
CommandParameter="{x:Bind ProductDetails.StockCode, Mode=OneWay}" />
</ic:EventTriggerBehavior>
<ic:EventTriggerBehavior EventName="RightTapped">
<ic:InvokeCommandAction Command="{x:Bind SetQuantityCommand, Mode=OneWay}"
CommandParameter="{x:Bind ProductDetails.StockCode, Mode=OneWay}" />
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Button>
</Grid>
<!--#endregion-->
<!--#region When quantity is positive-->
<Grid Padding="0"
x:Name="ProductWithPositiveQuantity"
Visibility="{Binding Quantity, Converter={StaticResource ProductQuantityVisibilityConverter}}"
Grid.Row="1"
Height="60"
Width="120">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="txtQuantity"
Style="{StaticResource QuantityButtonStyle}"
Command="{x:Bind IncreaseQuantityCommand,Mode=OneWay}"
FontSize="57"
Content="{x:Bind ProductDetails.Quantity, Mode=OneWay}"
CommandParameter="{x:Bind ProductDetails.StockCode, Mode=OneWay}">
</Button>
<Button Background="{StaticResource LightGray}"
Grid.Column="1"
Opacity="0.95"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Style="{StaticResource ButtonWithNoBorder}"
Command="{x:Bind DecreaseQuantityCommand, Mode=OneWay}"
CommandParameter="{x:Bind ProductDetails.StockCode, Mode=OneWay}">
<Image Stretch="None"
Source="ms-appx:///Images/HotCategories/MinusIcon.png" />
</Button>
<i:Interaction.Behaviors>
<ic:EventTriggerBehavior EventName="Holding">
<ic:InvokeCommandAction Command="{x:Bind SetQuantityCommand, Mode=OneWay}"
CommandParameter="{x:Bind ProductDetails.StockCode, Mode=OneWay}" />
</ic:EventTriggerBehavior>
<ic:EventTriggerBehavior EventName="RightTapped">
<ic:InvokeCommandAction Command="{x:Bind SetQuantityCommand, Mode=OneWay}"
CommandParameter="{x:Bind ProductDetails.StockCode, Mode=OneWay}" />
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Grid>
<!--#endregion-->
</Grid>
<Border Background="{StaticResource DarkGray}"
Height="20"
Width="120"
Grid.Row="1">
<TextBlock Text="{x:Bind ProductDetails.Description, Mode=OneWay}"
Padding="3,2,2,2"
FontSize="12"
FontWeight="SemiBold"
TextTrimming="CharacterEllipsis"
HorizontalAlignment="Left"
Foreground="White" />
</Border>
</Grid>
What I found that the for each update we were updating the ObservableCollection completely which ultimately multiplied the rendering time causing the flicker.
I updated the code to only update the list items whose values are changed in the collection so that they are the ones which are rendered again causing the less UI to re-render every time, hence removing the flicker.