Search code examples
c#xamlwindows-phone-8listpicker

How to Set Index of ListPicker without Executing ValueChanged Event


This problem has been driving me absolutely crazy. I have a ListPicker that is populated dynamically with several items. I have placed declared my SelectionChanged event handler in the Loaded event of my page. When the user clicks a certain item on the page, the ListPicker visibility will toggle from Collpased to Visible, and I set the values of the ListPicker. The issue is, the index of the ListPicker will be based upon the users settings, so out of three items the current index may be 1, not 0 as is the default. I need to show 1 as the current item in the ListPicker without the SelectionChanged event firing (which performs operations based on the current index). Then and only then when the user changes the selected item himself or herself do I need the SelectionChanged event to fire.

The main reason for this is not only does the user need to see his or her current setting in the ListPicker when it is displayed, but on the SelectionChanged event operations occur which overwrite what currently exists which is extremely confusing and not supposed to occur unless the user specifies.

What I currently have is as follows

XAML

<toolkit:ListPicker x:Name="lp" Visibility="Collapsed" Margin="12" Width="300"/>

XAML.CS

private void Page_Loaded(object sender, RoutedEventArgs e)
    {
        lp.SelectionChanged += lp_SelectionChanged;
    }

void EditableEllipse_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
    if (sender != null)
    {
        DependencyObject tappedElement = e.OriginalSource as UIElement;
        // find parent UI element of type PhotoThumbnail
        //PhotoThumbnail i = this.FindParentOfType<PhotoThumbnail>(tappedElement);
        i = this.FindParentOfType<PhotoThumbnail>(tappedElement);
        if (i != null)
        {
            BuildControl(i);
        }
    }
}

private void BuildControl(PhotoThumbnail pp)
    {
        switch(pp.NName)
        {
            case "flip":
                List<ListPickerItem> l = new List<ListPickerItem>();                    
                l.Add(new ListPickerItem { Name = "Flip_Vertical", Content = AppResources.App_Flip_Vertical });
                l.Add(new ListPickerItem { Name = "Flip_Horizontal", Content = AppResources.App_Flip_Horizontal });
                l.Add(new ListPickerItem { Name = "Flip_Both", Content = AppResources.App_Flip_Both });
                lp.ItemsSource = l;  //Code execution jumps from here to ValueChanged event immediately                  
                lp.Visibility = Visibility.Visible;
                lp.SelectedIndex = Settings.Flip.Value - 1;
                break;
        ..
        }
    }

private async void lp_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
            if (lp.SelectedIndex != -1) //always defaults to = 0
            {
                var item = (sender as ListPicker).SelectedItem;
                string name = ((ListPickerItem)item).Name;

                if (name != null)
                {
                        switch (name)
                        {
                            case "Flip_Vertical":
                                Settings.Flip.Value = 1;
                                ..perform process based on current Setting.Flip.Value..                                    break;
                            case "Flip_Horizontal":
                                Settings.Flip.Value = 2;
                                ..perform process based on current Setting.Flip.Value..
                                break;
                            case "Flip_Both":
                                Settings.Flip.Value = 3;
                                ..perform process based on current Setting.Flip.Value..
                                break;

                             ...
                          }
                }
            }

Solution

  • Try using an order of operation technique (by unhooking and rehooking the event)

    private void BuildControl(PhotoThumbnail pp)
    {
        switch(pp.NName)
        {
            case "flip":
    
                // unhook event
                lp.SelectionChanged -= lp_SelectionChanged;
    
                List<ListPickerItem> l = new List<ListPickerItem>();                    
                l.Add(new ListPickerItem { Name = "Flip_Vertical", Content = AppResources.App_Flip_Vertical });
                l.Add(new ListPickerItem { Name = "Flip_Horizontal", Content = AppResources.App_Flip_Horizontal });
                l.Add(new ListPickerItem { Name = "Flip_Both", Content = AppResources.App_Flip_Both });
                lp.ItemsSource = l;  //Code execution jumps from here to ValueChanged event immediately                  
                lp.Visibility = Visibility.Visible;
                lp.SelectedIndex = Settings.Flip.Value - 1;
    
                // after setting the index, rehook the event
                lp.SelectionChanged += lp_SelectionChanged;
    
                break;
        ..
        }
    }