0

XAML で次のように定義されたリストボックスがあります。

<ListBox x:Name="directoryList"
                 MinHeight="100" 
                 Grid.Row="0"
                 ItemsSource="{Binding Path=SelectedDirectories}"/>

SelectedDirectories は、タイプのリスト DataContext のプロパティです。List<DirectoryInfo>

リストボックスのデータ コンテキストであるクラスは、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));
            }
        }
    }
4

2 に答える 2

3

試す

ObservableCollection<DirectoryInfo> 

代わりに、理由もなく ListBox 全体の更新をトリガーしており、ホスティング クラスに 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 は何を動的に追加/削除するかを認識します。

于 2009-05-26T06:26:30.007 に答える
0

(以下の更新を参照) . WPF は問題なく動作しているようです。あなたのコードを新しいプロジェクトに入れました。ボタンをクリックして AddDirectory を呼び出すたびに、リストボックスが更新されます。これ以上コードを変更する必要はありません。 問題は別のようです.. 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 クラスに変更はありません。またはリストボックスの XAML。リストボックス、テキストボックス、およびボタンを含む DockPanel を持つ Window を作成しました。

更新:ポール ベッツは正しいです。Bound プロパティから毎回新しいリストを返すため、機能します。リストを使ったデータバインディングはいつも私を混乱させます。さらにいじくり回して、これを行う簡単な方法は次のとおりです。

  • 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);
         }
      }
    
于 2009-05-26T07:05:54.887 に答える