سؤال

لدي قاعدة قائمة محددة في XAML على النحو التالي:

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

المعدبات المحددة هي خاصية في قوائم DataContext من النوع List<DirectoryInfo>

الفئة التي هي DataContext لملابس ListBox تنفذ 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 يعمل بخير. أضع الشفرة في مشروع جديد. تحديثات ListBox كلما قمت بالنقر فوق الزر لاستدعاء AddDirectory. يجب ألا تحتاج إلى أي تغييرات رمز أخرى. يبدو أن المشكلة شيء آخر .. هل هناك خيوط متعددة في واجهة المستخدم الخاصة بك؟

لم يكن لدي نوع الفيلمكاننر. لذلك قمت بإنشاء دمية كما يلي.

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;      }
   }

لا توجد تغييرات على فئة filescannerstresenter. أو listbox الخاص بك xaml. قمت بإنشاء نافذة مع DockPanel تحتوي على ListBox الخاص بك، مربع النص وزر.

تحديث: بول بيتس هو الصحيح. يعمل لأنني أعيد قائمة جديدة في كل مرة من الممتلكات المربطة. تجلط البيانات مع قوائم تفسدني دائما. مع المزيد من العبث، الطريقة السهلة للقيام بذلك هي:

  • جعل filescanner # الدلائل إرجاع 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