绑定ListPicker.SelectedIndex问题

时间:2011-05-17 15:04:43

标签: xaml windows-phone-7 binding listpicker

我正在尝试在Windows Phone 7 UserControl中对ListPicker的SelectedIndex属性进行双向绑定。

设置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 个答案:

答案 0 :(得分:5)

SelectedIndex解决问题后移动ItemsSource

这是工作代码段

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

有人对此有解释吗?

答案 1 :(得分:3)

我的猜测是,在创建项目和项目存在之前,绑定的默认值为零。因此,在创建该项目之前,它会尝试选择第一个项目(零索引)。

尝试确保PickerSelectedIndex的ViewModel属性默认为-1 您可能还希望延迟设置绑定,直到创建项目。

答案 2 :(得分:1)

马特莱西是对的;绑定发生在数据项填充之前&amp;因此错误。如果你有一个SelectionChanged的事件处理程序,你会注意到,当页面/ listpicker加载时,它中的断点将被命中。以下是解决此初始化问题的一种方法:

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.                    
            }
         }            
    }

答案 3 :(得分:1)

我遇到了同样的问题,XAML中属性的排序没有帮助。在我的例子中,我将ItemsSource绑定到StaticResource上的属性,但我将SelectedIndex与我的页面的ViewModel的属性绑定。当我更改ItemsSource的绑定以绑定到ViewModel本身的属性(即复制了StaticResource的属性)时,我的问题消失了,我也能够对SelectedIndex执行双向绑定。

答案 4 :(得分:1)

我发现我的应用程序存在同样的问题。 但我注意到,当我删除ViewModel中ListPicker的所有元素时,就会发生这种情况。 因此,没有必要将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必须始终设置为有效值”。 现在问题解决了。