Search code examples
eventsuwpswitch-statementtogglewinui-3

WinUI Custom Toggle Switch with intermediate event


I have been scratching my head for some time over this.

I want to have toggle switch that fires an event when pressed and based on the event handler toggles if specific task is completed as expected.

So far:

  1. I could only attach PointerPressedEvent,which works fine.
  2. There seems to be no way to control toggling action for the switch on click.

Question:

  1. Shouldn't it be possible to click the toggle switch and toggle only if the desired action/task/method is completed.

Is this kind of control even possible to make with WinUI/UWP?

Thank you in advance for your guidance.


Solution

  • You can also do it this way. First of all, you need to install the CommunityToolkit.Mvvm NuGet package (v8.0.0-preview-4 or later) to make MVVM style easier.

    MainWindow.xaml

    <Window
        x:Class="ToggleSwitchSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <StackPanel Orientation="Vertical">
            <CheckBox
                Content="Awesome task should success"
                IsChecked="{x:Bind ViewModel.IsAwesomeTaskShouldSuccess, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                IsThreeState="False" />
            <ProgressRing HorizontalAlignment="Left" IsActive="{x:Bind ViewModel.AwesomeTaskCommand.IsRunning, Mode=OneWay}" />
            <ToggleSwitch
                x:Name="AwesomeToggleSwitch"
                IsOn="{x:Bind ViewModel.IsAwesomeTaskSuccessed, Mode=OneWay}"
                Toggled="AwesomeToggleSwitch_Toggled" />
        </StackPanel>
    
    </Window>
    

    MainWindow.xaml.cs

    using Microsoft.UI.Xaml;
    
    namespace ToggleSwitchSample;
    
    public sealed partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent();
            ViewModel = new MainPageViewModel();
        }
    
        public MainPageViewModel ViewModel { get; }
    
        private async void AwesomeToggleSwitch_Toggled(object sender, RoutedEventArgs e)
        {
            try
            {
                // Detatch the "Toggled" event to avoid multiple firing.
                this.AwesomeToggleSwitch.Toggled -= AwesomeToggleSwitch_Toggled;
                // Set the "IsOn" state to its previous state.
                this.AwesomeToggleSwitch.IsOn = !this.AwesomeToggleSwitch.IsOn;
                // Run the task and wait until it's completed.
                await ViewModel.AwesomeTaskCommand.ExecuteAsync(this);
            }
            finally
            {
                // Attach back the Toggled event.
                this.AwesomeToggleSwitch.Toggled += AwesomeToggleSwitch_Toggled;
            }
        }
    }
    

    MainWindowViewModel.cs

    using CommunityToolkit.Mvvm.ComponentModel;
    using CommunityToolkit.Mvvm.Input;
    using System.Threading.Tasks;
    
    namespace ToggleSwitchSample;
    
    [ObservableObject]
    public partial class MainPageViewModel
    {
        [ObservableProperty]
        // The CommunityToollkit-MVVM library will automatically create
        // "IsAwesomeTaskShouldSuccess" property for binding.
        private bool _isAwesomeTaskShouldSuccess;
    
        [ObservableProperty]
        // The CommunityToollkit-MVVM library will automatically create
        // "IsAwesomeTaskSuccessed" property for binding.
        private bool _isAwesomeTaskSuccessed;
    
        [RelayCommand]
        // The CommunityToollkit-MVVM library will automatically create
        // "AwesomeTasCommand" command.
        private async Task AwesomeTask()
        {
            bool awesomeTaskResult = await Task.Run(async () =>
            {
                bool result = false;
                await Task.Delay(3000);
                result = true;
                return result;
            });
    
            IsAwesomeTaskSuccessed = awesomeTaskResult && _isAwesomeTaskShouldSuccess is true;
        }
    }