8

我正在尝试在 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 的数据。

看不出哪里有问题...

4

5 回答 5

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}"/>

有人对此有解释吗?

于 2011-05-18T07:09:33.970 回答
3

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

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

于 2011-05-17T15:15:46.770 回答
1

马特·莱西是对的;绑定发生在数据项被填充之前,因此会出现错误。如果您有一个用于 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.                    
            }
         }            
    }
于 2011-05-17T17:03:08.557 回答
1

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

于 2011-06-01T13:10:00.983 回答
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 设置为有效值”。现在问题解决了。

于 2012-07-28T08:22:32.980 回答