简体   繁体   中英

How to MVVM toggleswitch in UWP

How to correctly setup toggleswitch with command? I am using behavior to launch command using Toggled event. However I have problem when user changed state of switch, but my model rejects it. I do not know how to correctly program it, so view rejects update if it was rejected by model.

Here are my attempts to do it (INotifyPropertyChanged details skipped for clarity):

1. One way command

class ToggleSwitchVm {
     public bool IsOn => Model.IsOn;
     public ICommand SwitchManipulated {get;}
}

When user manipulates ToggleSwitch state in UI changes, but it is not related to state in model. Also toggleswitch ignores PropertyChanged events, while it is calling command:

async void SwitchManipulatedCommand(bool? state) {
    if(!Model.SetNewState(state.Value)) { // if failed to set state raise PropertyChanged to refresh view
        RaisePropertyChanged(nameof(IsOn)); // this call is ignored :(
    }
}

2. Two way property?

class ToggleSwitchVm { 
 
    private void ModelOnPropertyChanged(object sender, PropertyChangedArgs args){
       if(args.PropertyName == nameof(Model.IsOn)){
          IsOn = Model.IsOn;
       }

    }


    private bool _isOn;
    public bool IsOn 
    { 
        get => _isOn;
        set {
                if(SetValue(ref _isOn, value))
                {  // true if model was manipulated
                    // View set value, or model set value?
                    if(!Model.SetState(value))
                    {
                         RaisePropertyChanged(nameof(IsON)); // ignored by view
                    }
                }
            }
    }
}

This is a mess, because both Model and View set IsOn property and there is no way to know which one set it.

How to MVVM toggleswitch in UWP

The ToggleSwitch IsOnProperty is DependencyProperty , that means it could use to bind data with two way model. And you have no need to process the IsOn proprty in command method. Please refer the following code to implement the feature.

Xaml Code

<Page.DataContext>
    <local:ViewModel />
</Page.DataContext>

<Grid>
    <ToggleSwitch
        Header="Toggle work"
        IsOn="{Binding IsOn, Mode=TwoWay}"
        OffContent="Do work"
        OnContent="Working"
        />
</Grid>

Code behind

public class ViewModel: INotifyPropertyChanged
{
    private bool _isOn;
    public bool IsOn
    {
        get { return _isOn; }
        set { Set(ref _isOn, value); }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
    {
        if (Equals(storage, value))
        {
            return;
        }

        storage = value;
        OnPropertyChanged(propertyName);
    }

    private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM