Search code examples
c#windows-phone-8mvvmdata-bindingwindows-phone

WP8 - Binding commands to buttons and switches in list


I am using MVVM pattern and I have LongListSelector in my page but I am not sure how to do these bindings:

  • I want in each row a button which do something with object in that row. I have this prepare in ViewModel:

    private RelayCommand<Module> goToTrackingPageCommand;
    
    public RelayCommand<Module> GoToTrackingPageCommand
    {
        get
        {
            return goToTrackingPageCommand
                ?? (goToTrackingPageCommand = new RelayCommand<Module>(
                     NavigateToTrackingPage));
        }
    }
    
    private void NavigateToTrackingPage(Module module)
    {
        App.Current.SelectedModule = module;
        navigationService.NavigateTo(new Uri("/Views/ModuleTrackingPage.xaml"), UriKind.Relative);
    }
    

    And I am trying to bind it like this:

    <Button x:Name="ShowButton" Content="Show" 
                            Command="{Binding GoToTrackingPageCommand}"
                            CommandParameter="{Binding}"/>
    

    It's not working because button is in datatemplate and when there is binding it goes to selected Module object but not to ViewModel. So my first question is how can I fix it?

  • Second one is little complicated I guess but hope both get easy solution. I want have in each row ToggleSwitch too and when value is changed I want to call http request. I have this in datatemplate:

    <toolkit:ToggleSwitch x:Name="LockSwitch" IsChecked="{Binding IsLock}" />
    

    I could change binding to TwoWay but I change value in object and I want to call method in ViewModel with Module argument. So have can I change this binding? Should I someway call method in ViewModel from my object? Or should I somehow tell ViewModel that this object has changed this value? Or should I bind Checked and Unchecked event?


Solution

  • Regarding the Buttons: You can access the "parent datacontext" with an elementName binding and set the command parameter:

    <Button Command="{Binding DataContext.GoToXyCommand, ElementName=LayoutRoot}" CommandParameter="{Binding}" />
    

    Regarding your second question:

    First, I would check if a toggle-button is the right solution, if changing the value triggers a process with a possibly longer duration.

    An example where WP does this is enabling/disabling Air-Plane Mode.

    I would do it the same way:

    • Bind to the property via TwoWayBinding
    • When the property is changed, start the updating process, disable the toggle button and show a progress indicator.

    EDIT: Here is and example from a ViewModel I recently used.

        public bool IsUpdatingPushEnabled
        {
            get { return _isUpdatingPushEnabled; }
            set { SetProperty(ref _isUpdatingPushEnabled, value); }
        }
    
        public bool IsPushEnabled
        {
            get { return _isPushEnabled; }
            set
            {
                if (!IsUpdatingPushEnabled)
                {
                    SetProperty(ref _isPushEnabled, value);
                    var t = SetPushAsync();
                }
            }
        }
    
        private async Task SetPushAsync()
        {
            IsUpdatingPushEnabled = true;
    
            try
            {
                var result = await _settingService.EnablePushAsync(IsPushEnabled);
                SetProperty(ref _isPushEnabled, result, "IsPushEnabled");
            }
            catch
            {
                //...
            }
    
            IsUpdatingPushEnabled = false;
        }