Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ToggleSwitch in UWP C#

Tags:

c#

xaml

uwp

I have a little question. I'm trying to create an UWP C# application, and I'm using toggle switches in the project. If I toggle the status of the ToggleSwitch from the software very often, the memory usage increases very much. Why is this happening?

The ToggleSwitch represents a boolean using binding.

I have created example code:

XAML:

<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ToggleSwitch Header="Test" HorizontalAlignment="Left" Margin="213,27,0,0" VerticalAlignment="Top" IsOn="{Binding Path=TestBool, Mode=TwoWay}"/>
    <CheckBox Content="Two-state CheckBox" Margin="108,162,0,806" IsChecked="{Binding Path=TestBool, Mode=TwoWay}"/>
    <Button Content="Start!" HorizontalAlignment="Left" Margin="69,58,0,0" VerticalAlignment="Top" Click="Button_Click"/>
</Grid>

C#:

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using System.ComponentModel;
using System.Runtime.CompilerServices;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace App1
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    /// 

    public sealed partial class MainPage : Page, INotifyPropertyChanged
    {
        private bool testBool = false;

        public bool TestBool { get { return testBool; } set { if (testBool != value) { testBool = value; OnPropertyChanged(); } } }

        public MainPage()
        {
            DataContext = this;
            this.InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < 10000; i++)
            {
                TestBool = !TestBool;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Do I do something that is not possible, what do I understand wrong?

When I replace the ToggleSwitch with a CheckBox, the memory usage increases much less.

Memory Usage

like image 424
Henri Avatar asked Apr 06 '18 11:04

Henri


People also ask

What is toggle control?

A toggle button allows the user to change a setting between two states. You can add a basic toggle button to your layout with the ToggleButton object. Android 4.0 (API level 14) introduces another kind of toggle button called a switch that provides a slider control, which you can add with a Switch object.

How do I create a custom control in UWP?

Like this we can give the desired control over our custom control to the user by binding them with our created dependency properties. Then go to MyUserControl1. xaml and add textblock and image from toolbox. Now we want to give the control to the user using our custom control so he/she can change text and image.

Does UWP use XAML?

UWP Applications You can create XAML-based applications with C# and C++, and make use of the Windows Runtime. New controls offer great improvements compared to WPF. Instead of using binding based on reflection, you can use compiled binding – with compilation errors if bound properties cannot be found.


1 Answers

It seems that a memory leak is occurring on your application, explaining why the GC failed to free it up.

Some considerations:

  • Why are you implementing INotifyPropertyChanged on the page level? You should implement it on a separate class. That class should hold the model and implement the INotifyPropertyChanged interface itself. That class is commonly denominated as a ViewModel, and as the name suggests holds the model for a View and it knows how to communicate any changes onto it.

    • Generally most of the problems with memory leaks with Bindings, that have been reported happen generally when utilizing compiled bindings, {x:Bind ...}, but you are utilizing the traditional bindings. You've correctly performed binding onto a dependency property, such as IsOn and also implemented the INotifyPropertyChanged on the source object, so I don't think that exists something inherently wrong with how you are spinning up the binding process.

    • You are performing 100 bindings update in a row, so even if the CPU usage should be a bit lower, it is expected that while you are iterating over the loop you will have your CPU usage increased. Ps: Since you have not marked your method as `async, you will be blocking the UI thread until your loop operation ends, which might be something that you could want to change. A binding update, is certainly a process with a couple of actions in the middle for each that's why I'm "confident" that the CPU usage might not be a big issue.

I don't actually have a guess, but I would strongly suggest to refactor your code to have the ViewModel class implemented as an extra class, and observe if the memory leaks observed seize to exist.

like image 92
André B Avatar answered Nov 01 '22 09:11

André B