绑定ListPicker.SelectedIndex问题

发布于 2024-11-07 23:23:36 字数 1682 浏览 0 评论 0原文

我正在尝试对 Windows Phone 7 用户控件中的 ListPicker 的 SelectedIndex 属性进行两种方式绑定。

当我设置 DataContext 时,它引发以下异常: SelectedIndex 必须始终设置为有效值。

这是 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 中的数据。

我看不出问题出在哪里...

I'm trying to do a two way binding of the SelectedIndex attribute of a ListPicker in a Windows Phone 7 UserControl.

It raises the following exception when I set the DataContext:
SelectedIndex must always be set to a valid value.

This is the XAML code

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

And the code behind in 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;
        }
    }

Putting a breakpoint in PickerSelectedIndex.get I can see that it is returned correctly (0).
I am sure that the problem is SelectedIndex="{Binding PickerSelectedIndex, Mode=TwoWay}" because deleting this line solves the problem, and I can see the ListPicker correctly loaded with the data from MyList.

I can't see where is the problem...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

抱着落日 2024-11-14 23:23:36

ItemsSource 之后移动 SelectedIndex 解决了问题。

这是工作片段

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

有人对此有解释吗?

Moving SelectedIndex after ItemsSource solved the problem.

This is the working snippet

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

Anyone have an explanation for this?

雨后咖啡店 2024-11-14 23:23:36

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

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

My guess would be that the binding is being applied with a default value of zero when created and before the items exist. It's therefore trying to select the first item (with a zero index) before that item is created.

Try making sure that the ViewModel property of PickerSelectedIndex defaults to -1.
You may also want to delay setting the binding until the items are created.

迎风吟唱 2024-11-14 23:23:36

马特·莱西是对的;绑定发生在数据项被填充之前因此出现错误。如果您有 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.                    
            }
         }            
    }

Matt Lacey is right; binding happens before the data items get populated & hence the error. If you have an event handler for SelectionChanged, you will notice that a breakpoint in it will be hit as the page/listpicker loads. Here is one way to get around this initialization issue:

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.                    
            }
         }            
    }
ヅ她的身影、若隐若现 2024-11-14 23:23:36

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

I had the same issue and the ordering of the properties in XAML didn't help. In my case, I was binding ItemsSource to a property on a StaticResource, but I was binding SelectedIndex with a property of my page's ViewModel. The moment I changed the binding of ItemsSource to bind to a property on the ViewModel itself (i.e. duplicated a property of the StaticResource), my issue went away and I was able to perform 2-way binding on SelectedIndex as well.

我喜欢麦丽素 2024-11-14 23:23:36

我在我的应用程序中发现了同样的问题。
但我注意到,当我删除绑定到 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 必须始终设置为有效值”。
现在问题解决了。

I've found the same problem with my app.
But I noticed that it happens when I delete all the elements of the list bounded to the ListPicker in the ViewModel.
So it isn't necessary to Bind SelectedIndex with another property since the problem depends only on the list bounded.
Here is my code which work fine for me:

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

The list in view model:

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

The handler for SelectionChanged:

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

Where Corsi is the class type of the list.

Here ListPicker template:

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

And, in the end, the method delete that checks if the list returned by IsolatedStorage is empty, if so, I put a fake empty element in the list bounded to the ListPicker, in order to not receive the error mentioned in this post.

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

                    }
                ----
        }

The strange thing was that, if the list was empty when the page has been loaded, nothing happens, instead, when I removed the last element from the list, the application raised the exception "SelectedItem must always be set to a valid value".
Now the problem is solved.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文