简体   繁体   中英

How to detect Pivot View using MVVM in WP7?

basically I have a pivot control in my WP7 app that contains 3 views. On each view I'm calling 1 of my 3 different web services that I run. What I'm trying to do is call the service only when they navigate to that particular view.

It's pretty simple using the code behind because all you do is use selected index with a switch statement and you can fire certain methods accordingly. Any idea on how to accomplish this from a view model?

NOTE: I'm using MVVM Light.

UPDATE: Here's my code that I would normally use:

private void PivotItem_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        int currentPivot = ResultsPivot.SelectedIndex;
        switch (currentPivot)
        {
            case 0:
                //Fire Method 1
                break;
            case 1:
                //Fire Method 2
                break;
            case 2:
                //Fire Method 3
                break;
            default:
                //Fire default method
                break;
        }
    }

The standard approach with MVVMLight is the split your view-model into data and commands. Most things you use databinding related, properties, etc. but commands actually do something.

In this case what you are calling "Fire Method 1" is an ordinary method that to conform to the pattern you have to convert to a command. If you already have commands you know what I am talking about.

The glue for events like SelectionChanged that you would have wired up with code-behind in MVVMLight is EventToCommand which is a XAML fragment that you put in the XAML with the pivot item instead of in the event hander.

So this is the pattern: EventToCommand is your key to hooking up XAML events to view-model commands without any code-behind. The best thing to do is use the MVVMLight samples to see how EventToCommand works because there are lots of ways to use it.

But here is the bare-bones version:

<controls:PivotItem Name="pivotItem">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <cmd:EventToCommand Command="{Binding SelectServiceCommand}"
                                CommandParameter="{Binding SelectedIndex, ElementName=pivotItem}"/>
        </i:EventTrigger>
        <!-- other stuff  -->
    </i:Interaction.Triggers>
</controls:PivotItem>

and to make this work the SelectServiceCommand has to actually exist in the view-model and it has to take a parameter and do the right thing for 0, 1, 2, 3, etc.

This can be solved in the following way

<controls:Pivot x:Name="PivotControl"  FontSize="18"  >
        <Custom:Interaction.Triggers>
            <Custom:EventTrigger EventName="SelectionChanged">
                <GalaSoft_MvvmLight_Command:EventToCommand x:Name="VideoPivotClicked"
                                                            Command="{Binding VideoPivotClicked,  Mode=OneWay}" PassEventArgsToCommand="True" />
            </Custom:EventTrigger>
        </Custom:Interaction.Triggers>

Then in your viewmodel you add this

      public RelayCommand<SelectionChangedEventArgs> VideoPivotClicked
  {
      get;
      private set;
  }

VideoPivotClicked = new RelayCommand<SelectionChangedEventArgs>(arg =>
                                                       {
                                                           PivotItem pivotItem = arg.AddedItems[0] as PivotItem;
                                                           Pivot pivot = pivotItem.Parent as Pivot;
                                                           Debug.WriteLine(pivot.SelectedIndex);
                                                       }
          );

You will not get the PivotItem that you are going to! and not the one you are leaving.

I haven't used MVVM Light directly, but you should be able to bind the selected index / item to a property on the view model. When that property is changed you could do your switch.

I like to keep things simple in situations like these where the View needs to notify the ViewModel that something that is so trivial changed (for example: A trivial combobox selection change that really has nothing to do with the view state (ie ViewModel)).

For your specific case, in your switch statement, just call a public method in your ViewModel. How to get the viewmodel reference? You can obtain that by the view's DataContext. So now your views can call public methods (and properties) within your viewModel.

For significant things stick with DataBinding. otherwise, just call directly. Saves so much time and hassle.

I get the index for the pivotItem that I'm leaving, not the PivotItem that I'm going to! .

Using this:

<controls:Pivot x:Name="pivMain" Title="{Binding AppName}" >
         <Custom:Interaction.Triggers>
            <Custom:EventTrigger EventName="SelectionChanged">
                    <cmd:EventToCommand Command="{Binding SelectServiceCommand}"          
                    CommandParameter="{Binding ElementName=pivMain, Path=SelectedIndex}"/>
             </Custom:EventTrigger>
        </Custom:Interaction.Triggers>

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