2011-05-11 4 views
1

Items 속성이 객체 컬렉션에 바인딩 된 ComboBox이 있습니다. 또한 전체 컬렉션에 바인딩 된 SelectedItem 속성이 있으며 ValueConverter 컬렉션의 요소를 검사하고 선택 될 1 개의 항목을 반환하도록 설계되었습니다. 이 부분은 작동합니다.ConvertBack (...)이 WPF ComboBox 선택 변경에서 실행되도록

사용자가 ComboBox에서 선택을 변경하면 ValueConverterConvertBack(...) 메서드가 호출되지 않습니다. 사용자가 선택한 항목을 가져 와서 컬렉션을 다시 검사하고 이전에 선택한 항목과 새로 선택한 항목을 적절히 편집해야하기 때문에 호출 된 ConvertBack(...)이 필요합니다.

나는이 접근법이 어색하다는 것을 알고 있지만, 그것이 길이다. 여기에 관련 코드는 다음과 같습니다

콤보 :

<ComboBox ItemsSource="{Binding}" SelectedItem="{Binding Path=., Converter={StaticResource ResourceKey=DataInputAssetChoiceSelectedItemConverter}}" /> 

ValueConverter :

public class DataInputAssetChoiceSelectedItemConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value != null) 
     { 
      foreach (CustomObject Choice in (Collection<CustomObject>)value) 
      { 
       if (Choice.IsSelected) 
       { 
        return Choice; 
       } 
      } 
      return ((Collection<CustomObject>)value).First(); 
     } 
     return null; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { //breakpoint...execution never gets here! 
     return null; 
    } 
} 

가 왜 ConvertBack(...) 이제까지

를 호출되지 않습니다? 그냥 내가 오해 한 것입니까 ComboBox? 나는 SelectedItem, SelectedValue, SelectedIndex을 사용하여이 접근법을 시도했으며 UpdateSourceTrigger, 다양한 바인딩 모드, DataTriggers를 사용하여 시도했지만 결코 호출 할 수없는 것 같습니다. ConvertBack(...). SelectionChanged 이벤트 만 사용하고 있습니까? 그렇다면 왜?

답변

3

속성에 바인딩하지 않으므로 바인딩에서 아무 것도 설정할 수 없습니다. DataContext 개체에 직접 바인딩하고 바인딩을 업데이트하지 않습니다.

{Binding Path=SomeProperty, Converter=...}이면 ConvertBack이 호출됩니다. 그것이 의미하는대로, 그것은 부르지 않을 것입니다.

+0

감사합니다. 이 동작을 기반으로 DataContext를 Binding의 소스로 사용하는 것은 아마도 Binding에 완전히 참여할 수 없으므로 허용되지 않아야합니다. SelectionChanged 이벤트를 사용하여 거기에서 DataCollection의 내용을 편집해야 할 것입니다. 데이터 모델을 변경하면 실제 속성에 바인딩 할 수 있지만 무서울 수 있습니다. – tyriker

+0

이 특정 상황에서 ConvertBack (...)이 작동하지 않는 이유를 설명 했으므로 답변으로 표시했습니다. 감사. – tyriker

2

당신이 맞다, 그것은 어색하지만 컬렉션 자체가 아닌 값 변환기의 컬렉션에 컬렉션을 추가하려고하기 때문에. 나는 컬렉션 더 알고 있다면 그것의 항목이 IsSelected 속성을 가지고 도움이 될 생각 :

public CustomCollection : Collection<CustomObject> { 
    CustomObject _current; 
    public CustomObject CurrentSelection { 
     get { return _current; } 
     set { 
      if (_current == value) 
       return; 

      if (_current != null) 
       _current.IsSelected = false; 

      if (value != null) 
       value.IsSelected = true; 

      _current = value; 
     } 
    } 
} 

그냥 _current은 적어도 컬렉션의 첫 번째 요소인지 확인하기 위해 약간의 여분의 추가합니다.

<ComboBox ItemsSource="{Binding}" SelectedItem="{Binding CurrentSelection}"> 

이제 변환기가 더 이상 필요하지 않습니다. 그러나 몇 가지 고려 사항이 누락되었습니다. 대신 ObservableCollection<T>을 사용하고 CurrentSelection이 변경되면 PropertyChanged 이벤트를 발생시켜 다른 속성이 해당 속성에 바인딩되거나 코드에서 변경된 경우 모든 바인딩이 적절히 업데이트되도록 할 수 있습니다.

편집 : 포장 모델

컬렉션을 감싸는 대신 사용자 지정 컬렉션 위와 같이 만드는 한 가지 쉬운 방법 :

public class CollectionWrapper : INotifyPropertyChanged { 
    public event PropertyChangedEventHandler PropertyChanged = (o,e)=>{}; 
    // never have to check for null 

    public CollectionWrapper(Collection<CustomObject> collection) { 
     Items = collection; 
    } 

    // unlikely to change, so let's prevent it for now 
    public Collection<CustomObject> Items { 
     get; 
     private set; 
    } 

    CustomObject _current; 
    public CustomObject CurrentSelection { 
     get { return _current; } 
     set { 
      if (_current == value) 
       return; 

      if (_current != null) 
       _current.IsSelected = false; 

      if (value != null) 
       value.IsSelected = true; 

      _current = value; 
      PropertyChanged(this, new PropertyChangedEventArgs("CurrentSelection")); 
     } 
    } 
} 

그런 다음이 객체가 데이터의 컨텍스트와 ComboBox 바인딩 변경된다 여기까지 :

<ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding CurrentSelection}"> 
+0

예, 데이터 모델을 변경하는 것이 가장 좋은 해결책 일 수 있지만 현재 상황에서는 쉽지 않습니다. 아마도이 특별한 바인딩에 대해이 컬렉션을 위해 불필요한 "래퍼"클래스를 만들 것입니다. – tyriker