Databound ListPicker SelectedItem становится пустым при изменении SelectedIndex

У меня есть ListPicker в моем приложении для Windows Phone 7, где свойства ItemsSource и SelectedIndex привязаны к моей ViewModel. SelectedIndex использует привязку Two Way. Элементы и SelectedIndex правильно заполняются при запуске приложения. Однако, когда я изменяю свойство SelectedIndex в моей ViewModel, TextBox ListPicker становится пустым, как если бы не было выбранного элемента. Если я перейду в полный режим и проверю, какой элемент выбран из списка, будет выбран правильный элемент.

Вот код xaml ListPicker:

<toolkit:ListPicker Name="TheListPicker" ItemsSource="{Binding TheItems}" CacheMode="BitmapCache" FullModeHeader="{Binding Path=Resources.TheHeader, Source={StaticResource LocalizedStrings }}" SelectedIndex="{Binding TheCurrentIndex, Mode=TwoWay}" IsEnabled="{Binding IsViewEnabled}" TabIndex="0" >
    <toolkit:ListPicker.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <TextBlock Text="{Binding Name}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="{StaticResource PhoneFontSizeMediumLarge}" />
            </StackPanel>
        </DataTemplate>
    </toolkit:ListPicker.ItemTemplate>
    <toolkit:ListPicker.FullModeItemTemplate>
        <DataTemplate>
            <StackPanel x:Name="item" Orientation="Horizontal" Margin="5, 24, 0, 24">
                <TextBlock Margin="15, 0, 0, 0" Text="{Binding Name}" FontSize="40" TextWrapping="Wrap" />
            </StackPanel>
        </DataTemplate>
    </toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>

Это упрощенная версия моей ViewModel:

[DataMember]
public ObservableCollection<ItemEntity> TheItems
{
    get
    {
        if (this.theItems == null)
        {
            this.theItems = new ObservableCollection<ItemEntity>();
        }

        return this.theItems;
    }
    set
    {
        this.theItems = value;
    }
}

[DataMember]
public int TheCurrentIndex
{
    get 
    {
        return this.theCurrentIndex;
    }
    set
    {
        if (value != this.theCurrentIndex)
        {
            this.theCurrentIndex = value;
            NotifyPropertyChanged("TheCurrentIndex");
            NotifyPropertyChanged("IsSomeOtherPropertyEnabled");
        }
    }
}

А вот соответствующий код из MainPage.xaml.cs (App_ViewModelChanged — это обработчик событий, вызываемый, когда некоторые асинхронные действия, выполняемые при запуске приложения, завершаются):

private void App_ViewModelChanged(object sender, ViewModelChangedEventArgs e)
{    
    BindToViewModel();
}

private void BindToViewModel()
{
    this.DataContext = this.ViewModel;
    this.ViewModel.IsViewEnabled = true;
}

private void SomeAsyncMethodCompleted(object sender, DetectCompletedEventArgs e)
{
    if (e.Error == null)
    {
        this.ViewModel.TheCurrentIndex = e.Result;
    }
}

Эта проблема возникает не постоянно. Бывает в 50% случаев. Кажется, это происходит только один раз за время жизни приложения, а затем никогда не повторяется. Кроме того, проблема начала появляться, когда я переключился с выпуска Silverlight Control Toolkit от февраля 2011 года на выпуск от августа 2011 года. Никогда не было этой проблемы раньше.

Это известная проблема?


person Julio Casal    schedule 05.10.2011    source источник
comment
Вы уверены, что вам не нужен SelectedItem?   -  person Derek Beattie    schedule 05.10.2011
comment
Я начал использовать SelectedIndex в надежде, что это решит ту же проблему, что и при использовании SelectedItem. Так что почти не имеет значения, какой из них вы используете.   -  person Julio Casal    schedule 05.10.2011
comment
Не могли бы вы поделиться с нами кодом, возможно, это поможет решить проблему   -  person BigL    schedule 05.10.2011
comment
Просто добавил немного кода. Очень упрощено по сравнению с реальной версией, но достаточно, чтобы понять идею.   -  person Julio Casal    schedule 05.10.2011
comment
Я пытаюсь выяснить, какой тип вы получаете из DetectCompletedEventArgs.Result, но, похоже, я нахожу только примеры, в которых вы получаете строку, а не int, но, возможно, это зависит от вашего AsyncMethod.   -  person BigL    schedule 05.10.2011
comment
Да не обращайте на это внимания. AsyncCompletedEventArgs — это пользовательский класс, созданный мной. e.Result - это просто int.   -  person Julio Casal    schedule 05.10.2011


Ответы (1)


Итак, причиной такого странного поведения было небольшое изменение в стиле ListPickerItem в наборе инструментов Silverlight Control Toolkit от августа 2011 года.

Вот как это выглядит в выпуске от августа 2011 года:

<Style TargetType="controls:ListPickerItem">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="Padding" Value="8 10"/>
    <Setter Property="Template">
        <!-- More Stuff Here -->
    </Setter>
</Style>

А вот как это выглядело в выпуске от февраля 2011 года:

<Style TargetType="controls:ListPickerItem">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="Padding" Value="8 6"/>
    <Setter Property="Template">
        <!-- More Stuff Here -->
    </Setter>
</Style>

Увидеть разницу? Они изменили заполнение ListPickerItem на 8 10 в новом выпуске, и каким-то образом это стало причиной проблемы. Возврат к 8 6 исправляет это. Не спрашивайте меня, почему.

Таким образом, в моем проекте я на самом деле не изменил файл Generic.xaml инструментария управления, а просто изменил определенные ресурсы ListPicker, чтобы указать новое дополнение для стиля ListPickerItem, например:

<toolkit:ListPicker Name="TheListPicker" ItemsSource="{Binding TheItems}" CacheMode="BitmapCache" FullModeHeader="{Binding Path=Resources.TheHeader, Source={StaticResource LocalizedStrings }}" SelectedIndex="{Binding TheCurrentIndex, Mode=TwoWay}" IsEnabled="{Binding IsViewEnabled}" TabIndex="0" >           
    <toolkit:ListPicker.Resources>
        <Style TargetType="toolkit:ListPickerItem">
            <Setter Property="Padding" Value="8 6"/>
        </Style>
    </toolkit:ListPicker.Resources>
    <toolkit:ListPicker.ItemTemplate>           
        <DataTemplate>           
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">           
                <TextBlock Text="{Binding Name}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="{StaticResource PhoneFontSizeMediumLarge}" />           
            </StackPanel>           
        </DataTemplate>           
    </toolkit:ListPicker.ItemTemplate>           
    <toolkit:ListPicker.FullModeItemTemplate>           
        <DataTemplate>           
            <StackPanel x:Name="item" Orientation="Horizontal" Margin="5, 24, 0, 24">           
                <TextBlock Margin="15, 0, 0, 0" Text="{Binding Name}" FontSize="40" TextWrapping="Wrap" />           
            </StackPanel>           
        </DataTemplate>           
    </toolkit:ListPicker.FullModeItemTemplate>           
</toolkit:ListPicker>

Такое маленькое изменение!

person Julio Casal    schedule 06.10.2011