2017-05-08 1 views
1

List<T> 속성에 대해 INotifypPropertyChanged이 상승하지 않는 이유는 무엇입니까?목록 <T> 속성에 대한 알림이 작동하지 않는 이유

public class NotifyPropertyChanged : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    public void OnPropertyChanged([CallerMemberName] string property = "") => 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); 
} 

public class TextWrapper 
{ 
    public string Text { get; set; } 
    public override string ToString() => Text; 
} 

public class ViewModel : NotifyPropertyChanged 
{ 
    public List<string> List { get; } = new List<string>(); 
    public TextWrapper Text { get; } = new TextWrapper(); 

    public void AddToList(string text) 
    { 
     List.Add(text); 
     OnPropertyChanged(nameof(List)); 
    } 

    public void ChangeText(string text) 
    { 
     Text.Text = text; 
     OnPropertyChanged(nameof(Text)); 
    } 
} 

public partial class MainWindow : Window 
{ 
    readonly ViewModel _vm = new ViewModel(); 

    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = _vm; 
    } 
} 

XAML :

이 MCVE을 고려

_vm.AddToList(...)를 호출하면 ListBox가 (비어있을 것입니다)를 업데이트하지 않는 동안, _vm.ChangeText(...) 제대로 TextBlock을 업데이트합니다 호출
<TextBlock Text="{Binding Text}" /> 
<ListBox ItemsSource="{Binding List}" /> 

. 왜?

는 참고 : 나는 약 ObservableCollection<T>을 알고 난에 대한 두 가지 가능한 해결 방법을 ( List에 세터를 추가 한 다음 다시 제 null을 가령 또는 DataContext/ ItemsSource 변경하도록 설정) 알고있다. 나는 지붕 아래에있는 것이 단지 TextWrapper보다 더 특별하다 List<T>가 궁금하다.

+0

사이드 노트 - 이것이 문제를 일으킬 수 있는지 확실하지 않지만'List'는 예약 된 이름입니다. 그것을 바꾸거나 "@"와 같이 접두사 "@"를 사용해보십시오. –

+0

@KamilSolecki 어떤 클래스의 이름으로 속성을 명명하는 것은 완전히 합법적입니다. 'List'는 _generic_ 클래스이기 때문에 이름은 결코 단순히 "List"가 아니라 "List'1"등이됩니다. –

답변

3

WPF 바인딩은 PropertyChanged 이벤트를 처리 할 때 생성되는 유효 값이 실제로 변경되지 않는 한 대상 속성을 업데이트하지 않습니다.

그래서 List 속성 값이 실제로 변경하지 않는 한

OnPropertyChanged(nameof(List)); 

를 호출, (당신이 요소를 추가 할 때하지 않는) 효과가 없습니다.

public List<string> List { get; } = new List<string>(); 

에 의해

public ObservableCollection<string> List { get; } = new ObservableCollection<string>(); 

를 교체하고이 같은 AddToList 방법을 쓰기 : 직접 TextWrapper에 결합 된 버젼 : 당신의 TextWrapper 클래스에 대한

public void AddToList(string text) 
{ 
    List.Add(text); 
} 

을 인스턴스 e에서 Binding은 재정의 된 ToString() 메서드를 호출하므로 TextWrapper의 Text 속성이 변경 될 때마다 다른 값을 생성합니다.

+0

왜'Text'를 호출하는 것이 효과가 있습니까? – Sinatr

+0

그리고? 두 속성의 인스턴스가 여전히 있습니다. 나는 이해하지 못한다. 그것은 어떤 종류의 비교 자와 관련이 있거나 무엇인가? 참고, 나는 (내 질문의 마지막 단락) 솔루션에 대한 질문입니다. 내 질문은 주로'Text' 및'List' 동작 ('ViewModel'의 속성)의 차이에 관한 것입니다. – Sinatr

+0

'ViewModel.Text'의 값은 변경되지 않고'TextWrapper.Text'만이 (그리고'TextWrapper' 안에 통지가 없습니다). – Sinatr

관련 문제