【问题标题】:ComboBox does not select proper item when bound to CompositeCollection绑定到 CompositeCollection 时,ComboBox 未选择正确的项目
【发布时间】:2013-05-26 03:45:32
【问题描述】:

我有一个绑定到动物集合的 ComboBox。我从中选择了我最喜欢的动物。我需要绑定项目上方的静态空项目。我使用 CompositeCollection 声明它。当 ComboBox 被绑定时,它不会选择我最初最喜欢的动物。我该如何解决?类似的问题here,但仍未解决。

观察:

  • 绑定到静态项目有效,即如果我没有最初最喜欢的动物,则选择静态项目。
  • 如果移除静态项目,问题就会消失。当然,这会使 CompositeCollection 和整个问题过时。

我已经应用了这些措施:

  • CollectionContainer 不能直接绑定到here 概述的属性。
  • 复合集合也按照建议 here 移动到静态资源。

完整的 C# 代码和 XAML 来演示问题:

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace WpfApplication1
{
    public class Animal
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class Zoo
    {
        private IEnumerable<Animal> _animals = new Animal[]
        {
            new Animal() { Id = 1, Name = "Tom" },
            new Animal() { Id = 2, Name = "Jerry" }
        };

        public Zoo(int initialId)
        {
            FavouriteId = initialId;
        }

        public int FavouriteId { get; set; }
        public IEnumerable<Animal> Animals { get { return _animals; } }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void BindComboBox(object sender, RoutedEventArgs e)
        {
            // Selecting the static item by default works.
            //DataContext = new Zoo(-1);

            // Selecting "Jerry" by default does not work.
            DataContext = new Zoo(2);
        }
    }
}

XAML

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1">

    <Window.Resources>
        <CollectionViewSource x:Key="AnimalsBridge" Source="{Binding Path=Animals}" />

        <CompositeCollection x:Key="AnimalsWithNullItem">
            <local:Animal Id="-1" Name="Pick someone..."/>
            <CollectionContainer Collection="{Binding Source={StaticResource AnimalsBridge}}" />
        </CompositeCollection>
    </Window.Resources>

    <StackPanel>
        <Button Content="Bind" Click="BindComboBox"/>

        <ComboBox x:Name="cmbFavourite"
            SelectedValue="{Binding Path=FavouriteId}"
            SelectedValuePath="Id" DisplayMemberPath="Name"
            ItemsSource="{StaticResource AnimalsWithNullItem}"/>
    </StackPanel>
</Window>

【问题讨论】:

    标签: wpf binding combobox selectedvalue compositecollection


    【解决方案1】:

    我没有解决您的问题的方法,而是另一种方法。我个人有专用于每个视图的视图模型。然后我会在视图模型上有一个属性来根据需要添加空值。我不喜欢这种方法,因为它可以更好地对我的视图模型进行单元测试。

    为您的示例添加:

    public class ZooViewModel
    {
        .....
    
    
        public IEnumerable<Animal> Animals { get { return _animals; } }
        public IEnumerable<Animal> AnimalsWithNull { get { return _animals.WithDefault(new Animal() { Id = -1, Name = "Please select one" }); } }
    }
    

    魔法组件

    public static class EnumerableExtend {
    
        public static IEnumerable<T> WithDefault<T>(this IEnumerable<T> enumerable,T defaultValue) {
            yield return defaultValue;
            foreach (var value in enumerable) {
                yield return value;     
            }
        }
    }
    

    然后在您的 XAML 中,您只需绑定到

    ComboBox x:Name="cmbFavourite"
            SelectedValue="{Binding Path=FavouriteId}"
            SelectedValuePath="Id" DisplayMemberPath="Name"
            ItemsSource="{Binding AnimalsWithNull }"/>
    

    现在您直接绑定到源并且可以正常控制绑定。另请注意,因为我们使用的是“yield”,所以我们不是创建一个新的枚举,而是只是迭代现有的列表。

    【讨论】:

    • +1 获得收益的黑魔法。不过,我仍然必须使用转换器从 ComboBox 的选定值中正确设置 ListViewItem 的属性。
    • 标记为答案,因为似乎不存在解决方案。项目也可以通过内置方法有效地添加:new[] { new Animal() { ... } }.Concat(_animals)
    猜你喜欢
    • 1970-01-01
    • 2012-02-11
    • 2023-03-12
    • 2010-09-23
    • 1970-01-01
    • 2020-12-11
    • 2012-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多