2013-05-30 3 views
4

ComboBox를 동물 컬렉션에 바인딩했습니다. 그것에서 나는 제일 좋아하는 동물을 선택한다. 바인딩 된 항목 위에 정적 null 항목이 필요합니다. CompositeCollection을 사용하여 선언합니다. ComboBox가 바인딩되면 은 내가 좋아하는 동물을 선택하지 않습니다. 어떻게 해결할 수 있습니까? 비슷한 문제 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

나는 당신의 문제에 대한 해결책이 아니라 대안을 해달라고합니다. 개인적으로 각보기 전용보기 모델이 있습니다. 그런 다음 필요에 따라 null 값을 추가하기 위해 뷰 모델에서 속성을 갖게됩니다. 내 뷰 모델의 더 나은 단위 테스트를 허용하기 때문에이 방법을 사용합니다. 귀하의 예를 들어

추가 : 당신은 소스에 직접 결합되어 이제

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

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에서 방금 바인딩하고 바인딩을 정상적으로 제어 할 수 있습니다. 또한 "yield"를 사용하기 때문에 새로운 열거 형을 생성하지 않고 기존 목록을 반복합니다.

+0

+1 검은 마술의 마법입니다. 나는 여전히 ComboBox의 선택된 값에서 ListViewItem의 속성을 올바르게 설정하기 위해 변환기를 사용해야했습니다. – helloserve

+0

솔루션이 존재하지 않기 때문에 대답으로 표시하십시오. 아이템은 내장 메소드에 의해 효율적으로 미리 추가 될 수 있습니다 :'new [] {new Animal() {...}} .Concat (_animals)' – idilov

관련 문제