WPF не обновляет список элементов списка - PullRequest
0 голосов
/ 03 февраля 2020

Я делаю небольшой проект для домашних животных в WPF, к которому я довольно нов.

Моя (частичная) цель такова:

  1. Открыть главное окно, которое содержит два В выпадающих списках «Система и документы»
  2. После загрузки этого окна я подключаюсь к файлу .mdb, содержащему таблицу со столбцами «Система» и «Документ».
  3. Создает ObservableCollection всех отдельных имен системы, хранящихся в файл базы данных и сохраняет их в виде arrayList, к которому привязан мой «Системный» список. Он успешно заполняет комбинированный список и выбирает первый элемент списка в качестве выбранного элемента.
  4. Выбранный элемент комбинированного списка «Система» - OneWayToSource, связанный со строкой с именем SystemFilter. Каждый раз, когда я изменял выбор, эта строка успешно обновлялась.
  5. С помощью этого SystemFilter мне удается отфильтровать документы и получить соответствующий список заголовков, который хранится в наблюдаемой коллекции TitleList и правильно заполняет комбинированный список «Document».

Работает нормально, однако каждый раз, когда я фильтрую базу данных, я создаю соединение с файлом, фильтрую содержимое, извлекаю его и закрываю соединение. Здесь, чтобы не открывать это соединение каждый раз, я решил загрузить все элементы в одну коллекцию ObservableCollection, называемую DocumentList, и намереваюсь выполнить для нее запросы LINQ. и результаты запроса, которые я храню в списках, которые я связываю со списком. ПРОБЛЕМА: Однако в этом случае список элементов Combobox не хочет обновлять автоматически, когда я выбираю другую систему. В чем может быть причина этого?

/ Примечание: я применил INotifyPropertyChanged в моей BaseViewModel и использую FodyWeaver для плетения своей сборки)

Оригинальная рабочая версия:

  • Два поля со списком:

            <!--System-->
            <TextBlock Margin="5 0 0 0" Text="System" FontWeight="Bold" HorizontalAlignment="Left"/>
            <ComboBox SelectionChanged="Combobox_Doc_Sys_SelectionChanged" x:Name="Combobox_Doc_Sys" 
                      ItemsSource="{Binding SystemList}" SelectedItem="{Binding SystemFilter,Mode=OneWayToSource}"
                      SelectedIndex="{Binding SystemIndex, Mode=TwoWay}"  Padding="2" Margin="5 0 5 0" >
            </ComboBox>
    
            <!--Document-->
            <TextBlock Margin="5 10 0 0" Text="Document" FontWeight="Bold" HorizontalAlignment="Left"/>
            <ComboBox x:Name="Combobox_Doc_Doc" SelectionChanged="Combobox_Doc_Doc_SelectionChanged" ItemsSource="{Binding TitleList}"  SelectedItem="{Binding TitleFilter, Mode=OneWayToSource}" 
                      Padding="2" Margin="5 0 5 0" SelectedIndex="0">
            </ComboBox>
    
  • Код позади MainWindow

        public MainWindow()
    {
        InitializeComponent();
        //Create ViewModel correalating to mainwindow
        this.DataContext = new MainWindowViewModel();
    
     }
    /// <summary>
    /// Event correlating the change of the selected item in Document section's System combobox
    ///// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Combobox_Doc_Sys_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        //Call ViewModel's function to filter documentlist based on the Selected system
        MainWindowViewModel.GetListOfTitle();
        //MainWindowViewModel.GetListOfTitle2();
    
        // Restores the selection to the first item in Document section's Document combobox
        Combobox_Doc_Doc.SelectedIndex = 0;
    }
    
  • Функция GetListOfTitle () с подключением к функции Файл .mdb:

       public static void GetListOfTitle()
    {
        //List that will store the list of the title
    
        //filtering  SQL
        string sysFilterSQL = $"SELECT * FROM DocList WHERE System='{SystemFilter}'";
    
        //Clear List for safety sake
        TitleList.Clear();
    
    
        using (OleDbConnection MyConnection = new OleDbConnection(ConnectStringDocList))
        {
            OleDbCommand command = new OleDbCommand(sysFilterSQL, MyConnection);
            command.Connection = MyConnection;
            MyConnection.Open();
    
            OleDbDataReader reader = command.ExecuteReader();
    
            //We fill up TitleList with the list of the titles filtered by "system"
            while (reader.Read())
            {
                var item = reader.GetString(2);
                TitleList.Add(item);
            }
    
            //Close reader
            reader.Close();
            //Close connection
            MyConnection.Close();
        }
    
    }
    
  • Параметры

     public static ObservableCollection<string> TitleList { get; set; } = new ObservableCollection<string>();
    

    publi c stati c string SystemFilter {get; набор; } = String.Empty;

Когда я перехожу на новую версию, где сначала успешно заполняю DocumentList с документами. Метод GetListofTitle2:

        internal static void GetListOfTitle2()
    {

        TitleList = (from s in DocumentList where s.System == $"{SystemFilter}" select s.Title).ToList();

    }

С:

        public static ObservableCollection<DocumentModel> DocumentList { get; set; } = new ObservableCollection<DocumentModel>();
    //--------------------------------------------------------------------------------------------//
    public static string SystemFilter { get; set; } = String.Empty;
    //--------------------------------------------------------------------------------------------//

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

В этой новой версии TitleList снова обновляется правильно, но не обновляется в интерфейсе: / В чем проблема? Я хотел бы решить его, потому что это решение кажется чище, чем при каждом открытии соединения и загрузке в файл .mdb

Спасибо за заранее полученные ответы

ОБНОВЛЕНИЕ: Если я изменю вторую версию до используйте observableCollections и измените GetListofTitle2 следующим образом:

        public static void GetListOfTitle2()
    {
        TitleList =new ObservableCollection<string>((from s in DocumentList where s.System == $"{SystemFilter}" select s.Title).ToList());
    }

Он все еще не обновляет комбинированный список, даже если TitleList содержит правильные элементы.

Ответы [ 2 ]

2 голосов
/ 03 февраля 2020
  1. Если вы измените экземпляр TitleList в модели, модель должна реализовать интерфейс INotifyPropertyChanged, и вы должны запустить событие PropertyChanged, как описано здесь (также, в последствии, посмотрите здесь ).
  2. Если ссылка на TitleList остается прежней, но изменяется (добавляет или удаляет элементы) , он должен реализовывать INotifyCollectionChanged и это именно то, что ObservableCollection делает.

Этот код:

TitleList = new ObservableCollection<string>(...);

Имеет вид 1 : вы меняете TitleList экземпляр.

Но вы используете авто-свойство, которое не вызывает событие PropertyChanged, поэтому привязка не обновляется:

// this is an auto-property
public List<string> TitleList { get; set; }

// it's equivalent to:
private List<string> _titleList;
public List<string> TitleList
{
  get => _titleList;
  set => _titleList = value;
}    

Вы должны запустить PropertyChanged событие в блоке set:

private List<string> _titleList;
public List<string> TitleList
{
  get => _titleList;
  set
  {
    // if the new value is the same as the old, just do nothing
    if (Equal(_titleList, value))
      return;

    _titleList = value;
    // This call will raise the event
    NotifyPropertyChanged();
  }
} 
0 голосов
/ 03 февраля 2020

Как сказал Орас (извините, я не могу добавлять комментарии), вам нужно сообщить об изменении вашего свойства, ObservableCollection сигнализирует, когда один из его элементов изменяется, но он поступает из самой коллекции объектов ... конечно, если этот объект изменился, инициализированный новой наблюдаемой коллекцией, он не может сигнализировать о наличии модификации. Я надеюсь, что вы понимаете ...

Вы должны реализовать INotifyPropertyChanged и запустить свойство, измененное при повторной инициализации. Другое решение состоит в том, чтобы очистить эту коллекцию, а затем заполнить ее вашим запросом.

Я не англичанин sh, поэтому я надеюсь, что я разъясню свои объяснения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...