2009-06-16 2 views
3

I는 3 층 깊이가 트리 뷰에서의 데이터 바인딩과 UI,상쾌한 WPF

 
-MAIN 
->:SUB1 
    >:SUB2 
    >:SUB2 
-X:SUB1 
    X:SUB2 
SUB1 
SUB1 

> 및 X는 (백엔드 결정) 특정 항목의 상태를 나타내는 그래픽을 나타낸다.

Observable Dictionary를 사용하여이 트리에 바인딩합니다 (ICollectionChanged 이벤트가 있음). . 위에서 언급 한 그래픽, 그것은 (즉 < IMG 소스 바인더 제본 할 수 있도록 경로 = "{바인딩 경로 상태 열거를 변환하는 사용자 정의 변환기를 사용하여 바인더 제본하는

 

ObservableDictionary<string,CustomClass> mainitems; 

public class CustomClass{ 
    ObservableDictionary<string, InnerClass> sub1item; 
    // Bunch of properties and methods in this class 
    // INotify not implemented 
} 

public class InnerClass{ 
    // Bunch of properties and methods in this class 
    // INotify not implemented 
    public SomeEnum Status{ 
     get{ return this.status; } 
    } 
} 
 

: 구조는 다음과 같이이다 = 무언가, 변환기 = {StaticResource someconverter}, 모드 = 원 웨이 "/ >).

질문 : 나는 새로운 상태로에서는 CustomClass의 sub1item 사전을 업데이트 할 때

내 문제는, 그것이 UI에 업데이트하지 않습니다. INotify 작업을 구현하는 것이 효과적 일지 모르지만 어디서 업데이트해야하는지 정확히 어떻게해야하는지 모르겠습니다.

편집 :

 

<TreeView Name="tvInstance" ItemsSource="{Binding}" TreeViewItem.Selected="tviSelected" IsTextSearchEnabled="True"> 
    <TreeView.ItemContainerStyle> 
     <Style> 
      <Setter Property="TreeViewItem.IsExpanded" Value="{Binding Path=Value.Expanded, Mode=TwoWay}" /> 
     </Style> 
    </TreeView.ItemContainerStyle> 
    <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate ItemsSource="{Binding Path=Value.CustomClass}" ItemContainerStyle="{x:Null}"> 
       <StackPanel Orientation="Horizontal"> 
       <Label Content="{Binding Path=Key}"/> 
      </StackPanel> 
      <HierarchicalDataTemplate.ItemTemplate> 
       <HierarchicalDataTemplate ItemsSource="{Binding Path=Value.AnotherClass}"> 
        <StackPanel Orientation="Horizontal"> 
         <Image Source="{Binding Path=Value.Status, Converter={StaticResource convertstatus} }" 
          Width="10" Height="10"/> 
         <Label Content="{Binding Path=Key}" /> 
        </StackPanel> 
        <HierarchicalDataTemplate.ItemTemplate> 
         <DataTemplate> 
          <StackPanel Orientation="Horizontal"> 
           <Image Source="{Binding Path=Value, Converter={StaticResource convertstatus} }" 
          Width="10" Height="10"/> 
           <Label Content="{Binding Path=Key}" /> 
          </StackPanel> 
         </DataTemplate> 
        </HierarchicalDataTemplate.ItemTemplate> 
       </HierarchicalDataTemplate> 
      </HierarchicalDataTemplate.ItemTemplate> 
     </HierarchicalDataTemplate> 
    </TreeView.ItemTemplate> 
</TreeView> 
 

편집 : 내 mainclass 내에서는 CustomClass, 내 InnerClass의 모든 INotifyProperty 이벤트를 추가 한 후, 그것은 여전히 ​​작동하지 않는 다음과 같이 트 리뷰에 대한 내 XAML 템플릿입니다 . ObservableDictionary의 Dr. WPF 버전을 사용하고 있습니다. 사전을 사용하는 것은 많은 조회가 필요하므로 내 응용 프로그램에 중요합니다. 도움! 그에서 INotifyPropertyChanged 내가 UI 업데이트하려는 속성에 구현 될 필요가에

에필로그

이 페이지의 답변은 정확합니다.

사전을 바인딩하면 너무 많은 문제가 발생하여 ObservableCollection과 Dictionary를 모두 유지한다는 것을 알았습니다. 검색과 바인딩을위한 사전을 사용했습니다. (둘 다 객체에 대한 동일한 참조를 사용하기 때문에 콜렉션과 O (n) 연산만으로 쉽게 제거 할 수있었습니다).

UI 업데이트와 관련하여이 페이지의 다른 게시물을 참조하십시오.

+0

sub1item 사전을 다시 인스턴스화합니까? 그렇다면 INotifyPropertyChanged를 포함하는 클래스에 INotifyPropertyChanged를 구현해야합니다. – rmoore

+0

CustomClass에는 sub1item = new ObservableDictionary를 설정하는 Refresh() 메서드가 있습니다. <..>(); 그런 다음 모든 InnerClass 항목을 다시 가져옵니다. 그러나, 그들은 거의 같은 항목입니다.난 단지 변경된 것들을 업데이트하고 싶다. 예. 변경 사항을 철회하십시오. – apandit

+0

이 문제를 해결할 방법을 찾았습니까? – Zenuka

답변

1

이 조금 긴, 여기에있을 것입니다 내 추측 할 수있다 :

public class CustomClass : INotifyPropertyChanged 
{ 
    public CustomClass() 
    { 
    sub1item = new ObservableDictionary<string, InnerClass>(); 
    // This next line may not be necessary... Changes might propogate up. 
    sub1item.CollectionChanged +=() => NotifyPropertyChange("Sub1Item"); 
    } 

    private ObservableDictionary<string, InnerClass> sub1item; 
    public ObservableDictionary<string, InnerClass> Sub1Item 
    { 
    get { return sub1item; } 
    private set { sub1item = value; NotifyPropertyChange("Sub1Item"); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
    if (PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(info)); 
    } 
    } 
} 

public class InnerClass : INotifyPropertyChanged 
{ 
    public SomeEnum Status 
    { 
    get { return this.status; } 
    private set { this.status = value; NotifyPropertyChange("Status"); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
    if (PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(info)); 
    } 
    } 
} 

그냥이 상태 = 뭔가를 호출하여 상태를 업데이트해야합니다, 그리고 직접 this.status

을 통해 편집 : 업데이트 된 상태 인 단일 개체 만 업데이트하려는 경우이 작업을 수행 할 것인지 잘 모르겠습니다. 나는 이것이 Sub1Item이 변경되었음을 알릴 것이라고 의심하지만, mainitems는 개별 객체에 대해 알지 못할 것입니다. 구현에 따라 다릅니다.당신이 당신이 어딘가에 C#으로

<DataTemplate DataType="{x:Type myClrNamespace:InnerClass}"> 
    <Grid> 
     <TextBlock Text={Binding Path=Status}/> 
    </Grid> 
</DataTemplate> 
... 
<ListBox x:Name="listStatus"/> 

그리고 제대로에만 업데이트 된 상태를 업데이트합니다 바인딩 한 후, Sub1Item에 결합했다에서는 CustomClass위한 DataTemplate을을 만든 경우

, 당신은 할 수 : listStatus = mainlist[0].Sub1Item;를 본 후 귀하의 TreeView ItemTemplate 귀하의 예를 들어, 나는 더 이상 모르겠다. 귀하의 하위 항목에 대한

기본적으로
public class InnerClass: INotifyPropertyChanged 
{ 
    private string _propertyName; 

    //Implemented from INotifyPropertyChanged 
    public event PropertyChangedEventHandler PropertyChanged; 

    public string PropertyName 
    { 
     get { return _propertyName; } 
     set 
     { 
       _propertyName = value; 
       OnPropertyChanged("Name or Property Data"); 
     } 
    } 

    //Just using string as an example, send whatever data you'd like 
    protected void PropertyChanged(string name) 
    { 
     //Check to make sure the event is wired. 
     if(PropertyChanged != null) 
     { 
       //Fire event 
       PropertyChanged(this, name); 
     } 
    } 
} 

은,이 사건 화재가와에서는 CustomClass 객체까지 전달합니다

+0

sub1item.CollectionChanged + = ... 행을 추가했지만 (Dictionary의 CollectionChanged 이벤트가 보호 된 이후로는 할 수 없습니다) 모든 것을 시도했습니다. 또한, NotifyChange 및 NotifyPropertyChanged를 사용하고있는 것으로 나타났습니다. 그리고 나는 그들이 동일하다고 가정합니다 ... 다른 아이디어? – apandit

0

당신은, 이벤트를 사용해야하는 클래스가에서 INotifyPropertyChanged를 구현하고있다, 그것은 다음과 같이 보일 것입니다. 그런 다음 필요에 따라 CustomClass에서 이러한 이벤트를 처리하게하고 UI를 업데이트하라는 기본 객체까지 다른 이벤트를 발생시킵니다.

1

관찰 가능한 컬렉션은 WPF에서보기 항목 컬렉션을 새로 고치기 위해 INofityCollectionChanged을 구현합니다.

그러나 상태가 업데이트 되려면 데이터에 INotifyPropertyChanged을 구현해야합니다.

  • 보기에 표시하려는 각 클래스에서이를 구현해야하므로 WPF는 속성이 변경되고 속성 중 변경된 사항을 알 수 있습니다. 구현은 간단하다

...

// Should implement INotifyPropertyChanged if the dictionary itself 
// can be changed and not only its items 
public class CustomClass { 
    ObservableDictionary sub1item; 
    // Bunch of properties and methods in this class 
    // INotify not implemented 
} 


public class InnerClass : INotifyProperyChanged { 
    // Bunch of properties and methods in this class 
    // INotify not implemented 
    public SomeEnum Status{ 
     get{ return this.status; } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 



protected void NotifyPropertyChanged(string propertyName) 
{ 
    if(PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 


// where ever this.status is changed directly, 
// call NotifyPropertyChanged("Status") 
// (at end of that method) 
// 
// if this.status is changed from outside class (if public), 
// then add a public method NotifyStatusChanged() which calls 
// NotifyPropertyChanged("Status") 
// 
// If Status property has a set{} then if new value != this.status, 
// call NotifyPropertyChanged("Status") at end of setter 

} 
0

ObservableDictionary(Of TKey, TValue) - VB.NET

일반 기능 목록 :

  • ObservableDictionary (TKEY의, TValue)
  • AddRange 한 번만 통보.
  • 일반 이벤트Args (Of TKey, TValue)
  • NotifyDictionaryChanging (Of ​​TKey, TValue) - 취소 작업을 허용하는 CancelEventArgs의 하위 클래스입니다. 유형 "작업"

    공용 클래스 작업의 클래스의 예를 작업

0

는 :

{ 

    //Implemented from INotifyPropertyChanged 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 

개인 문자열 텍스트에서 INotifyPropertyChanged; 측면에

public string Text 
    { 
     get { return text; } 
     set { 
      text = value; 
      NotifyPropertyChanged("Text"); 

      } 
    } 

}

는 그 가치는 당신이 얻을 목록보다는 ObservableCollection에의 rathan를 사용할 필요가 있음을 기억합니다 메모 유형의 컬렉션에 데이터 바인딩 할 때 동적으로 ItemSource를 업데이트. 목록에 알리지 않습니다.