Xaml 绑定ListPicker.SelectedIndex问题

Xaml 绑定ListPicker.SelectedIndex问题,xaml,windows-phone-7,binding,listpicker,Xaml,Windows Phone 7,Binding,Listpicker,我正在尝试在WindowsPhone7用户控件中对ListPicker的SelectedIndex属性进行双向绑定 <Grid x:Name="LayoutRoot"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions>

我正在尝试在WindowsPhone7用户控件中对ListPicker的SelectedIndex属性进行双向绑定

<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时会引发以下异常:
SelectedIndex必须始终设置为有效值。

<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>
这是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中的代码

<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>
    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;
        }
    }
private observeCollection myList=null;
公共可观测集合MyList
{
获取{返回this.myList;}
设置
{
if(值!=this.myList)
{
this.myList=值;
NotifyPropertyChanged(“MyList”);
this.PickerSelectedIndex=0;
}
}
}
私有整数选择器selectedIndex=0;
公共整数选择器选择索引
{
得到
{
返回此.pickerSelectedIndex;
}
设置
{
this.pickerSelectedIndex=值;
}
}
选择器selectedIndex.get中放置断点
我可以看到它已正确返回(
0
)。 我确信问题是
SelectedIndex=“{Binding PickerSelectedIndex,Mode=TwoWay}”
,因为删除这一行可以解决问题,并且我可以看到ListPicker正确加载了MyList中的数据

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

我看不出问题出在哪里…

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

<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>
尝试确保
PickerSelectedIndex
的ViewModel属性默认为-1。

您可能还希望延迟设置绑定,直到创建项目。

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

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

itemsource
之后移动
SelectedIndex
解决了问题

<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>
这是工作片段

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


有人对此有什么解释吗?

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

我发现我的应用程序也存在同样的问题。
<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>
但我注意到,当我在ViewModel中删除列表中绑定到ListPicker的所有元素时,就会发生这种情况。 因此,没有必要将SelectedIndex与另一个属性绑定,因为问题只取决于绑定的列表。 以下是我的代码,对我来说很好:

<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>
<toolkit:ListPicker x:Name="ListaCorsi"
                                SelectionChanged="ListaCorsi_SelectionChanged"
                                ItemsSource="{Binding ListaCorsiUser}"
                                SelectionMode="Single" 
                                ItemTemplate="{StaticResource CorsiDataTemplate}" 
                                ItemsPanel="{StaticResource ItemsPanelTemplateListaCorsi}"/>
其中,Corsi是列表的类类型

<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>
这里是ListPicker模板:

<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>
<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的列表中放置一个伪空元素,以避免收到本文中提到的错误

<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>
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()});

                    }
                ----
        }
if(this.CorsoSelected!=null)
{
---
List corsi=新列表(DBHelper.GetCorsiByUserId(PassaggioValori.UserId));
如果(corsi.Count>0)
{
this.ListaCorsiUser=新的可观测集合(corsi);
}
其他的
{
this.ListaCorsiUser=newobserveCollection(new List(){new Corsi()});
}
----
}
奇怪的是,如果加载页面时列表为空,则什么也不会发生,相反,当我从列表中删除最后一个元素时,应用程序引发了异常“SelectedItem必须始终设置为有效值”。
现在问题解决了。

这可能没有什么帮助,但我发现有趣的是,这段代码在WPF中似乎工作得很好。对不起,我是Silverlight开发人员,您能解释一下“PickerSelectedIndex的ViewModel属性”是什么意思吗?行“private int PickerSelectedIndex=0;”将属性设置为默认值为零。这就是我所指的。如果保留SelectedIndex绑定,但去掉ItemTemplate,会发生什么?我不编写WP7,但在WPF中,这段代码(减去ItemTemplate)可以正常工作。删除
ItemTemplate=“{StaticResource PickerTemplate}”
并不能解决问题。。。无论如何,谢谢你!我也有同样的问题。很奇怪,这似乎取决于xaml属性的顺序。。。我认为这是一个错误,因为xaml属性应该独立于它们的顺序工作。事实上,这是工作在wpf没有问题也表明了这一点。是的,工作为我太。最初我是绑定SelectedIndex={binding Source={StaticResource AppSettings},Path=ChosenFavorite,Mode=TwoWay}。我必须将值的检索移到视图模型。
<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>