Проблема привязки ListPicker.SelectedIndex - PullRequest
8 голосов
/ 17 мая 2011

Я пытаюсь выполнить двустороннюю привязку атрибута SelectedIndex ListPicker в UserControl Windows Phone 7.

При установке DataContext возникает следующее исключение: SelectedIndex must always be set to a valid value.

Это код XAML

<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <toolkit:ListPicker
        Grid.Row="0"
        x:Name="List1"
        SelectionChanged="Picker_SelectionChanged"
        SelectedIndex="{Binding PickerSelectedIndex, Mode=TwoWay}"
        ItemTemplate="{StaticResource PickerTemplate}"
        ItemsSource="{Binding MyList}"/>
</Grid>

И код в DataContext

    private ObservableCollection<MyClass> myList = null;
    public ObservableCollection<MyClass> MyList
    {
        get { return this.myList; }
        set
        {
            if (value != this.myList)
            {
                this.myList= value;
                NotifyPropertyChanged("MyList");

                this.PickerSelectedIndex = 0;
            }
        }
    }

    private int pickerSelectedIndex = 0;
    public int PickerSelectedIndex
    {
        get
        {
            return this.pickerSelectedIndex;
        }
        set
        {
            this.pickerSelectedIndex= value;
        }
    }

Установка точки останова в PickerSelectedIndex.get Я вижу, что она возвращается правильно (0).Я уверен, что проблема SelectedIndex="{Binding PickerSelectedIndex, Mode=TwoWay}", потому что удаление этой строки решает проблему, и я вижу, как ListPicker правильно загружен данными из MyList.

Я не вижу, в чем проблема ...

Ответы [ 5 ]

5 голосов
/ 18 мая 2011

Перемещение SelectedIndex после того, как ItemsSource решило проблему.

Это рабочий фрагмент

<toolkit:ListPicker
    Grid.Row="0"
    x:Name="List1"
    SelectionChanged="Picker_SelectionChanged"
    ItemTemplate="{StaticResource PickerTemplate}"
    ItemsSource="{Binding MyList}"
    SelectedIndex="{Binding PickerSelectedIndex, Mode=TwoWay}"/>

У кого-нибудь есть объяснение этому?

3 голосов
/ 17 мая 2011

Я полагаю, что привязка применяется со значением по умолчанию, равным нулю, при создании и до того, как элементы существуют.Поэтому он пытается выбрать первый элемент (с нулевым индексом) до его создания.

Попробуйте убедиться, что для свойства ViewModel PickerSelectedIndex по умолчанию установлено значение -1. ​​
Вы также можетеотложить настройку привязки, пока элементы не будут созданы.

1 голос
/ 28 июля 2012

Я обнаружил ту же проблему с моим приложением.Но я заметил, что это происходит, когда я удаляю все элементы списка, связанные с ListPicker в ViewModel.Поэтому нет необходимости связывать SelectedIndex с другим свойством, поскольку проблема зависит только от ограниченного списка.Вот мой код, который отлично работает для меня:

<toolkit:ListPicker x:Name="ListaCorsi"
                                SelectionChanged="ListaCorsi_SelectionChanged"
                                ItemsSource="{Binding ListaCorsiUser}"
                                SelectionMode="Single" 
                                ItemTemplate="{StaticResource CorsiDataTemplate}" 
                                ItemsPanel="{StaticResource ItemsPanelTemplateListaCorsi}"/>

Модель списка:

private ObservableCollection<Corsi> _listaCorsiUser;
    public ObservableCollection<Corsi> ListaCorsiUser 
    {
        get { return _listaCorsiUser; }
        set
        {
            _listaCorsiUser = value;
            OnPropertyChanged("ListaCorsiUser");
        }
    }

Обработчик для SelectionChanged:

void ListaCorsi_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
            if (ListaCorsi.SelectedItem != null)
            {
                ---
                this.CorsoSelected = ListaCorsi.SelectedItem as Corsi;
            }
    }

Где Corsiэто тип класса списка.

Здесь шаблон ListPicker:

<DataTemplate x:Key="CorsiDataTemplate">
        <Grid>
            <Grid.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="Black" Offset="0"/>
                    <GradientStop Color="#FF3523FF" Offset="0.25"/>
                    <GradientStop Color="Black" Offset="1"/>
                    <GradientStop Color="#FF3523FF" Offset="0.75"/>
                </LinearGradientBrush>
            </Grid.Background>
            <TextBlock TextWrapping="Wrap" Text="{Binding NomeCorso}" FontSize="24" FontFamily="Freestyle Script" TextAlignment="Center"/>
        </Grid>
    </DataTemplate>

И, в конце концов, метод delete, который проверяет, является ли список, возвращаемый IsolatedStorage, пустым, если это так,Я поместил поддельный пустой элемент в список, связанный с ListPicker, чтобы не получать ошибку, упомянутую в этом посте.

if (this.CorsoSelected != null)
        {
            ---

                    List<Corsi> corsi = new List<Corsi>(DBHelper.GetCorsiByUserId(PassaggioValori.UserId));
                    if (corsi.Count > 0)
                    {
                        this.ListaCorsiUser = new ObservableCollection<Corsi>(corsi);

                    }
                    else
                    {
                        this.ListaCorsiUser = new ObservableCollection<Corsi>(new List<Corsi>() { new Corsi()});

                    }
                ----
        }

Странная вещь заключалась в том, что, если список был пуст, когда страницабыл загружен, ничего не происходит, вместо этого, когда я удалил последний элемент из списка, приложение вызвало исключение "SelectedItem всегда должен быть установлен в допустимое значение".Теперь проблема решена.

1 голос
/ 01 июня 2011

У меня была та же проблема, и упорядочение свойств в XAML не помогло.В моем случае я связывал ItemsSource со свойством StaticResource, но я связывал SelectedIndex со свойством ViewModel моей страницы.В тот момент, когда я изменил привязку ItemsSource для привязки к свойству самого ViewModel (т.е. продублировал свойство StaticResource), моя проблема исчезла, и я также смог выполнить двустороннее связывание с SelectedIndex.

1 голос
/ 17 мая 2011

Мэтт Лэйси прав; привязка происходит до заполнения элементов данных и, следовательно, ошибки. Если у вас есть обработчик событий для SelectionChanged, вы заметите, что точка останова в нем будет достигнута при загрузке страницы / списка. Вот один из способов обойти эту проблему инициализации:

private void SomeListPicker_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        // Make sure we don't handle the event during initiation.
        if (e.RemovedItems != null && e.RemovedItems.Count > 0)
        {
            if (this.SomeListPicker.SelectedItem != null)
            {
               // Do actual stuff.                    
            }
         }            
    }
...