2013-05-30 55 views
4

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

观察:

  • 绑定到静态项工作,即如果我没有初始喜爱的动物的静态项被选中。
  • 如果删除了静态项目,问题就会消失。当然这会使CompositeCollection和这个整个问题过时。

我已经应用了这些措施:如概述here

  • 一个CollectionContainer不能直接绑定到一个属性。
  • 如建议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> 

回答

4

我没有一个解决问题的方法,而是一种替代。我个人有查看模型专用于每个视图。然后,我会在视图模型上有一个属性,根据需要添加空值。我支持这种方法,因为它允许更好地对我的视图模型进行单元测试。

对于你的榜样补充:

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”,我们不是创建一个新的枚举,而只是遍历现有的列表。

+0

+1对于黑魔法的收益。尽管如此,我仍然必须使用转换器来正确设置ComboBox的选定值的ListViewItem属性。 – helloserve

+0

标记为答案,因为解决方案似乎不存在。项目可以通过内置方法有效地预置:'new [] {new Animal(){...}} .Concat(_animals)' – idilov

相关问题