WPF Listbox는 다시 그리기되지 않습니다
문제
XAML에 listbox가 다음과 같이 정의되어 있습니다.
<ListBox x:Name="directoryList"
MinHeight="100"
Grid.Row="0"
ItemsSource="{Binding Path=SelectedDirectories}"/>
selectedDirectories는 유형의 데이터 콘텍스트 목록에있는 속성입니다. List<DirectoryInfo>
Listbox의 Datacontext 인 클래스는 inotifyPropertyChanged를 구현합니다. 컬렉션이 변경되면 항목이 목록에 성공적으로 추가되지만 목록 상자가 크기를 조정하여리스트 박스를 다시 그리기 할 때까지 디스플레이가 업데이트되지 않습니다.
왜 아이디어가 있습니까?
편집 : inotifyPropertyChanged 구현
public class FileScannerPresenter : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private FileScanner _FileScanner;
public FileScannerPresenter()
{
this._FileScanner = new FileScanner();
}
public List<DirectoryInfo> SelectedDirectories
{
get
{
return _FileScanner.Directories;
}
}
public void AddDirectory(string path)
{
this._FileScanner.AddDirectory(path);
OnPropertyChanged("SelectedDirectories");
}
public void OnPropertyChanged(string property)
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
해결책
노력하다
ObservableCollection<DirectoryInfo>
대신 - 이유없이 전체 목록 상자의 새로 고침을 트리거하고 호스팅 클래스가 inotifyPropertyChanged를 구현할 필요가 없습니다. 창의 속성 일 수 있습니다. 열쇠는 속성을 새 인스턴스로 설정하지 않는 것입니다. 그래서:
class SomeWindow : Window {
public ObservableCollection<DirectoryInfo> SelectedDirectories {get; private set;}
SomeWindow() { SelectedDirectories = new ObservableCollection<DirectoryInfo>(); }
public void AddDirectory(string path) {
SelectedDirectories.Add(new DirectoryInfo(path));
}
}
해당 FileScanner 클래스를 사용하면 inotifyCollectionChanged를 구현해야합니다. 그렇게하면 ListBox는 동적으로 추가/제거해야 할 사항을 알고 있습니다.
다른 팁
(아래 업데이트 참조). WPF는 잘 작동하는 것 같습니다. 나는 당신의 코드를 새로운 프로젝트에 넣었습니다. 버튼을 클릭하여 AddDirectory를 호출 할 때마다 ListBox가 업데이트됩니다. 더 이상 코드 변경이 필요하지 않아야합니다. 문제는 다른 것 같습니다 .. UI에 여러 스레드가 있습니까?
Filescanner 유형이 없었습니다. 그래서 나는 다음과 같이 더미를 만들었습니다.
public class FileScanner
{
string _path;
public FileScanner()
{ _path = @"c:\"; }
public List<DirectoryInfo> Directories
{
get
{
return Directory.GetDirectories(_path).Select(path => new DirectoryInfo(path)).ToList();
}
}
internal void AddDirectory(string path)
{ _path = path; }
}
FilescannerPresenter 클래스에 변경되지 않습니다. 또는 ListBox XAML. ListBox, TextBox 및 버튼이 포함 된 DockPanel이있는 창을 만들었습니다.
업데이트: Paul Betts가 맞습니다. 바운드 속성에서 매번 새 목록을 반환하기 때문에 작동합니다. 목록과의 데이터 바인딩은 항상 나를 엉망으로 만듭니다. 더 땜질하면 쉽게 수행 할 수있는 방법은 다음과 같습니다.
- Filescanner#Directories를 반환하게하십시오
ObservableCollection<DirectoryInfo>
(구현INotifyCollectionChanged
당신을 위한). 모든 서명을 끝까지 변경 하여이 유형이 대신이 유형을 반환합니다.List<DirectoryInfo>
Filescanner와 FilescannerPresenter 자체는 inotifyxxx 인터페이스를 구현할 필요가 없습니다.
// in FileScanner class def public ObservableCollection<DirectoryInfo> Directories { get { return _DirList; } } internal void AddDirectory(string path) { _path = path; //var newItems = Directory.GetDirectories(_path).Select(thePath => new DirectoryInfo(thePath)).ToList(); //_DirList.Concat( newItems ); -- doesn't work for some reason. foreach (var info in Directory.GetDirectories(_path).Select(thePath => new DirectoryInfo(thePath)).ToList()) { _DirList.Add(info); } }