2011-02-11 3 views
3

에 변경 통지 WPF/XAML 양식과 유사한, 사전에 속성에 데이터 바인딩 :건물은 내가 가지고 사전

<TextBox Text="{Binding Path=Seat[2B].Name}"> 

Seat은 비행기 객체의 속성 IDictionary<String, Reservation>로 노출된다. 내 윈도우의 코드 내에서

class airplane 
{ 
    private IDictionary<String, Reservation> seats; 
    public IDictionary<String, Reservation> Seat 
    { 
     get { return seats; } 
     // set is not allowed 
    } 
} 

는 좌석 (b)의 값은 때때로 변경을 한 후, 나는 속성이 변경 UI를 통지합니다.

class MyWindow : Window 
{ 
    private void AddReservation_Click(object sender, EventArgs e) 
    { 
     airplane.Seat["2B"] = new Reservation(); 
     // I want to override the assignment operator (=) 
     // of the Seat-dictionary, so that the airplane will call OnNotifyPropertyChanged. 
    } 
} 

는 내가 사전 IObservable 경우 내가 그것에 변화를 관찰 할 수 있도록, 볼을 검토 한 결과,하지만 될 것 같지 않습니다.

NotifyPropertyChanged 수 있도록 비행기 클래스에서 사전에 대한 변경 사항을 "catch"하는 좋은 방법이 있습니까?

답변

12

박사 WPF는이 링크에서 ObservableDictionary를 만들었습니다 : http://drwpf.com/blog/2007/09/16/can-i-bind-my-itemscontrol-to-a-dictionary/

업데이트 :다음 링크에서 박사 WPF에 의해 코멘트는 그가 더 자신이 그래서 다음과 같은 변화가해야이 문제를 해결했다고 말한다 http://10rem.net/blog/2010/03/08/binding-to-a-dictionary-in-wpf-and-silverlight

작은 변화가

했다 : 이상 또한

을 요구, 가산은이 링크에서 만들어졌다

// old version 
public TValue this[TKey key] 
{ 
    get { return (TValue)_keyedEntryCollection[key].Value; } 
    set { DoSetEntry(key, value);} 
} 

// new version 
public TValue this[TKey key] 
{ 
    get { return (TValue)_keyedEntryCollection[key].Value; } 
    set 
    { 
     DoSetEntry(key, value); 
     OnPropertyChanged(Binding.IndexerName); 
    } 
} 
+0

전에도 그 기사를 읽었습니다. 내 기억이 실패합니다 ... –

+0

@ H.B .: 여기 같은 것입니다. 저는 경험에 비추어서 Dr.WPF가하는 모든 일들을 알고 있습니다. 그러나 나는 대답을 게시하기 전에 그것을 시험해야한다고 생각했습니다. 그래서 샘플 앱을 저장하려고 할 때 로컬 버전을 대체하고 싶다면 질문이 생겼습니다. :) 그렇다면 기억이났습니다. –

+0

하하, 그 중 하나입니다 :) –

1

이 문제를 해결하는 한 가지 방법은 사전을 캡슐화하는 것입니다. 그런 다음 인터페이스에 알리고 사전에 대한 액세스를 제어 할 수 있습니다. 즉, 대괄호를 사용하여 대괄호를 사용하여 내부 값 통지를 제기하십시오.

1
당신은 항상 ObservableDictionary 생산하기 위해 사전 (또는 IDictionary)에서 파생 할 수

:

public class ObservableDictionary<TKey, TVal>:IDictionary<TKey, TVal>, IObservable 
{ 
    private Dictionary<TKey, TVal> _data; 

    //Implement IDictionary, using _data for storage and raising NotifyPropertyChanged 
} 

당신은 가능성이 발생할 것이다 가장 큰 문제는 직접 값으로 변화를 감지 할 수 없을 것입니다 ; KVP 만 추가 및 제거합니다. 이를 수행하려면 _data를 List<ObservableKeyValuePair>으로 변경하고 거기에 IObservable을 구현하고 생성하거나 수신하는 모든 새 요소에 핸들러를 연결하면 KVP의 NotifyPropertyChanged에 응답하고 부모 클래스의 NotifyValueChanged를 발생시킵니다.

2

변경 알림 구현을 시작하기 전에 수행하려는 작업에 대해 명확한 아이디어가 필요합니다. 주어진 키가있는 사전에 저장된 객체가 변경 될 때 UI를 업데이트하려면 그 중 하나입니다. 사전에 저장된 객체의 속성이 변경 될 때 UI가 업데이트되기를 원한다면 그것은 완전히 다른 것입니다.

즉, Reservation.Name이 변경 될 때 UI를 업데이트하려면 변경 알림을 수행하려면 Reservation 개체가 필요합니다. Seat[2B]이 다른 Reservation으로 설정된 경우 UI를 업데이트하려면 사전에 변경 알림을 수행해야합니다.

+0

우수한 점, 그리고 나는 그것에 대해 완전히 명확하지 않았습니다. 예약 변경시 사전 (또는 사전 소유자, 비행기)에 알림을 보내고 싶습니다. (숙박 시설의 특성이 바뀌면 예약이 자체 통지를 할 것입니다 ... 그 부분은 쉽습니다) – abelenky

3

INotifyPropertyChanged 인터페이스를 구현하는 클래스를 만들고이 클래스로 값을 랩핑하고 사전에 사용할 수 있습니다. 나는 비슷한 문제를 가지고 있었고, 다음했다 : 그 후

class Parameter : INotifyPropertyChanged //wrapper 
{ 
    private string _Value; 
    public string Value //real value 
    { 
     get { return _Value; } 
     set { _Value = value; RaisePropertyChanged("Value"); } 
    } 

    public Parameter(string value) 
    { 
     Value = value; 
    } 

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; 
    public void RaisePropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 
public class ViewModel 
{ 
    public Dictionary<string, Parameter> Parameters 
} 
<ItemsControl ItemsSource="{Binding Path=Parameters, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Margin="3" > 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="Auto"/> 
        <ColumnDefinition Width="*"/> 
       </Grid.ColumnDefinitions> 
       <Label Grid.Column="0" Content="{Binding Path=Key}" Margin="3" /> 
       <TextBox Grid.Column="1" Text="{Binding Path=Value.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True" Margin="3" /> 
      </Grid> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

, 당신은 사전에 값을 변경하는 경우, 당신은 UI의 변화를 볼 수 있습니다.