Search code examples
slidermaui

MAUI: How to disable the DragCompletedCommand of Slider when click lower time


Using this thread I implemented the slider reduction prevention logic on my MAUI application.

But I have a DragCompletedCommand also in the Slider and which will do some actions. Here when clicking the lower time on slider at that time also the DragCompletedCommand was hitting and doing those actions. How can I disable that?

I tried like below: Added a bool variable on viewmodel and check it's value before doing the actions.

public ICommand DragCompletedCommand => new Command(OnDragCompleted);

private void OnDragCompleted(object obj)
{
    if (invokeDragCompleted)
    {
        //My actions
    }
}

I am setting that bool value from homepage.xaml.cs page's ValueChanged event.

public void SliderValueChanged(object sender, ValueChangedEventArgs args)
{
    try
    {
        Slider slider = (Slider)sender;
        IsIncrease = args.NewValue > args.OldValue;
        if (!IsIncrease)
        {
            hpvm.InputTransparent = true;
            slider.Value = args.OldValue;
            value = args.OldValue;
            hpvm.invokeDragCompleted = false;
        }
        else
        {
            hpvm.InputTransparent = false;
            slider.Value = args.NewValue;
            value = args.NewValue;
            hpvm.invokeDragCompleted = true;
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception:>>" + ex);
    }
}

But this event is always firing when the timer runs and hitting if and else block alternatively. So the bool value is getting true from here and doing the actions on the Viewmodel. Is there any way to set the bool value to false when choosing a lower time?

My Slider code:

<Slider 
    x:Name="watchme_slider"
    Grid.Column="1"
    BackgroundColor="White"
    MinimumTrackColor="#1c98d7"
    MaximumTrackColor="#9a9a9a"
    ThumbImageSource="ic_thumb_xx.png"
    ValueChanged="SliderValueChanged"
    InputTransparent="{Binding InputTransparent}"
    Maximum="0.166666667"
    Minimum="0"
    DragCompletedCommand="{Binding DragCompletedCommand}"
    HorizontalOptions="FillAndExpand"/>

The timer is running in every second that hits the ValueChanged event. If the user touch or drag the Slider, at that time also ValueChanged event is firing. Is there any way to find which type of event is triggered?

Update

Updated the slider code like below:

<Slider 
    x:Name="watchme_slider"
    Grid.Column="1"
    BackgroundColor="White"
    MinimumTrackColor="#1c98d7"
    MaximumTrackColor="#9a9a9a"
    ThumbImageSource="ic_thumb_xx.png"
    ValueChanged="SliderValueChanged"
    InputTransparent="{Binding InputTransparent}"
    Maximum="0.166666667"
    Minimum="0"
    HorizontalOptions="FillAndExpand">
    <Slider.Behaviors>
        <toolkit:EventToCommandBehavior
            EventName="DragCompleted"
            Command="{Binding Source={x:Reference page}, Path=BindingContext.DragCompletedCommand}"
            CommandParameter="{Binding Source={x:Reference watchme_slider}}"/>
    </Slider.Behaviors>
</Slider>

Updated HomePageViewModel class with partial keyword:

public partial class HomePageViewModel : BaseViewModel, INotifyPropertyChanged

Commented below ICommand:

//public ICommand DragCompletedCommand => new Command(OnDragCompleted);

Added RelayCommand and rename the function to DragCompleted:

[RelayCommand]
public void DragCompleted(object obj)
{
    var slider = obj as Slider;
    Debug.WriteLine("slider.Value:>>" + slider.Value);
    Debug.WriteLine("preValue:>>" + preValue);
    if (slider.Value > preValue)
    {
        Debug.WriteLine("do some work");
        preValue = slider.Value;
    }
}

Solution

  • You set the slider.Value = args.OldValue; in SliderValueChanged event. That's the reason why both if and else block are hitted.

    From my understanding, you want to do some actions in DragCompletedCommand only when the slider increase its value. Right?

    I may add a new field maybe call it preValue in ViewModel to store the previous value of slider.

    private double preValue;
    

    And check if the current value is larger,

        [RelayCommand]
        public void DragCompleted(object obj)
        {
            var slider = obj as Slider;
            if (slider.Value > preValue)
            {
                Debug.WriteLine("do some work");
                preValue = slider.Value;
            }
        }
    

    Here is the XAML, I use EventToCommandBehavior from Maui CommunityToolkit.

    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             ...
             Title="HomePage"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             x:Name="page">
    
        <Slider 
            x:Name="watchme_slider"
            Grid.Column="1"
            BackgroundColor="White"
            MinimumTrackColor="#1c98d7"
            MaximumTrackColor="#9a9a9a"
            ThumbImageSource="ic_thumb_xx.png"
            ValueChanged="SliderValueChanged"
            InputTransparent="{Binding InputTransparent}"
            Maximum="0.166666667"
            Minimum="0"     
            HorizontalOptions="FillAndExpand">
            <Slider.Behaviors>
                <toolkit:EventToCommandBehavior
                EventName="DragCompleted"
                Command="{Binding Source={x:Reference page}, Path=BindingContext.DragCompletedCommand}"
                CommandParameter="{Binding Source={x:Reference watchme_slider}}"
                    />
            </Slider.Behaviors>
        </Slider>