문제

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);
         }
      }
    
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top