WPF ListBox не обновляется при обновлении Bound List - PullRequest
0 голосов
/ 17 сентября 2018

У меня проблема с моим ListBox, так как он не обновляется, когда я обновляю список, к которому он привязан. Я уже видел много таких же вопросов, но ни один из его ответов не решил мою проблему. Моя ситуация заключается в том, что у меня есть ComboBox, что при выборе параметра, мой ListBox будет отображать параметры на основе выбора ComboBox. Я знаю, что список, связанный с ListBox, обновляется, но элементы не отображаются в списке. Если я вручную добавлю элемент в объявление класса ViewModel списка, то этот элемент появится, но это не то, что я хочу (или, может быть, это так, и я вижу это под неправильным углом). Вот мой код:

ВМ для моего ComboBox и вызов для обновления ListBox:

public class SelectorEventosViewModel : ObservableCollection<SelectorEvents>,INotifyPropertyChanged
{
    private SelectorEvents _currentSelection;
    public SelectorEventosViewModel()
    {
        PopulaSelectorEvents();
    }

    private void PopulaSelectorEvents()
    {
        Add(new SelectorEvents {Key = "evtInfoEmpregador", Value = "S1000"});
        Add(new SelectorEvents {Key = "evtTabEstab", Value = "S1005"});
        Add(new SelectorEvents {Key = "evtTabRubricas", Value = "S1010"});
    }

    public SelectorEvents CurrentSelection
    {
        get => _currentSelection;
        set
        {
            if (_currentSelection == value)
                return;
            _currentSelection = value;
            OnPropertyChanged(nameof(CurrentSelection));
            ValueChanged(_currentSelection.Key);
        }
    }
    //Here I detect selectiong and then call for the Update in my ListBox VM
    private void ValueChanged(string value)
    {
        EventFilesViewModel.Instance.GetFiles(value);
    }

    protected override event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Вот мой код для виртуальной машины ListBox:

public class EventFilesViewModel : ObservableCollection<EventFiles>
{
    private static EventFilesViewModel _instance = new EventFilesViewModel();
    public static EventFilesViewModel Instance => _instance ?? (_instance = new EventFilesViewModel());
    private string[] _filesList;
    //This would be my Update function, based on the ComboBox selection I would show some files in my ListBox, but it's not
    public void GetFiles(string ptr)
    {
        _filesList = Directory.GetFiles(@"\\mp-2624/c$/xampp/htdocs/desenv2/public/esocial/eventos/aguardando/");
        Clear();
        foreach (string file in _filesList)
        {
            var r = new Regex(ptr, RegexOptions.IgnoreCase);
            var tempFiles = new EventFiles {Key = file, Value = file.Split('/')[9]};
            if (r.Match(file).Success)
            {
                Add(tempFiles);
            }
        }
        OnPropertyChanged(nameof(EventFilesViewModel));
    }

    protected override event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

В моих моделях SelectorEvents и FileEvents реализована функция INotifyPropertyChanged.

Мой XAML:

<ComboBox DataContext="{StaticResource ResourceKey=SelectorEventosViewModel}" Name="EventoBox" FontSize="20" SelectedIndex="0" Margin="20 10" Width="150" 
                                          ItemsSource="{StaticResource ResourceKey=SelectorEventosViewModel}"
                                          DisplayMemberPath="Value"
                                          SelectedItem="{Binding CurrentSelection}"
                                          IsSynchronizedWithCurrentItem="True"/>

<ListBox DataContext="{StaticResource ResourceKey=EventFilesViewModel}"
                                             Grid.Column="0" Name="EventoListBox" FontSize="20" Margin="10 10"
                                             HorizontalAlignment="Stretch"
                                             ItemsSource="{StaticResource ResourceKey=EventFilesViewModel}"
                                             IsSynchronizedWithCurrentItem="True"
                                             DisplayMemberPath="Value">

Заранее спасибо.

1 Ответ

0 голосов
/ 17 сентября 2018

Так что я не уверен, как вы намеревались сделать эту работу, но вот решение, которое больше MVVM.

По сути, мы сворачиваем обе ваши виртуальные машины в MainWindowVm, который обрабатывает сообщения между ними. Таким образом, ваши дочерние виртуальные машины остаются независимыми друг от друга и, следовательно, более настраиваемыми в дальнейшем.

Основываясь на моем тестировании, привязка для вашего ItemSource для второй записи не удалась (я добавил кнопку и проверил значение ItemSource во время выполнения после подтверждения обновления EventFilesViewModel).

EventFilesViewModel

public class EventFilesViewModel : INotifyPropertyChanged
{
   public ObservableCollection<EventFiles> EventFiles { get; } = new ObservableCollection<EventFiles>();

   private string[] _filesList;

   //This would be my Update function, based on the ComboBox selection I would show some files in my ListBox, but it's not
   public void GetFiles(string ptr)
   {
      _filesList = Directory.GetFiles(@"\\mp-2624/c$/xampp/htdocs/desenv2/public/esocial/eventos/aguardando/");
      EventFiles.Clear();
      foreach (string file in _filesList)
      {
         var r = new Regex(ptr, RegexOptions.IgnoreCase);
         var tempFiles = new EventFiles { Key = file, Value = file.Split('/')[9] };
         if (r.Match(file).Success)
         {
            EventFiles.Add(tempFiles);
         }
      }
      OnPropertyChanged(nameof(EventFilesViewModel));
   }

   public event PropertyChangedEventHandler PropertyChanged;

   [NotifyPropertyChangedInvocator]
   protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
   {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
   }
}

SelectorEventosViewModel

public class SelectorEventosViewModel : INotifyPropertyChanged
{
   public ObservableCollection<SelectorEvents> SelectorEvents { get; set; } = new ObservableCollection<SelectorEvents>();

   private SelectorEvents _currentSelection;

   public SelectorEventosViewModel()
   {
      PopulaSelectorEvents();
   }

   private void PopulaSelectorEvents()
   {
      SelectorEvents.Add(new SelectorEvents { Key = "evtInfoEmpregador", Value = "S1000" });
      SelectorEvents.Add(new SelectorEvents { Key = "evtTabEstab", Value = "S1005" });
      SelectorEvents.Add(new SelectorEvents { Key = "evtTabRubricas", Value = "S1010" });
   }

   public SelectorEvents CurrentSelection
   {
      get => _currentSelection;
      set
      {
         if (_currentSelection == value)
            return;

         _currentSelection = value;
         OnPropertyChanged();
      }
   }

   public event PropertyChangedEventHandler PropertyChanged;

   [NotifyPropertyChangedInvocator]
   protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
   {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
   }
}

MainWindowVm.cs

public class MainWindowVm : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;

   [NotifyPropertyChangedInvocator]
   protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
   {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
   }

   public SelectorEventosViewModel SelectorEventosViewModel { get; } = new SelectorEventosViewModel();

   public EventFilesViewModel EventFilesViewModel { get; } = new EventFilesViewModel();

   public MainWindowVm()
   {
      // CRITICAL--ensures that your itemsource gets updated
      SelectorEventosViewModel.PropertyChanged += SelectorEventosViewModel_PropertyChanged;
   }

   private void SelectorEventosViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
   {
      // CRITICAL--ensures that your itemsource gets updated
      EventFilesViewModel.GetFiles(SelectorEventosViewModel.CurrentSelection.Key);
   }
}

MainWindow.xaml

<Window x:Class="_52370275.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:_52370275"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800"
        d:DataContext="{d:DesignInstance local:MainWindowVm}">
   <Grid>
      <Grid.RowDefinitions>
         <RowDefinition Height="Auto"/>
         <RowDefinition Height="Auto"/>
         <RowDefinition Height="Auto"/>
         <RowDefinition />
      </Grid.RowDefinitions>
      <ComboBox
         Name="EventoBox"
         FontSize="20"
         SelectedIndex="0"
         Margin="20 10"
         Width="150"
         Grid.Row="0"
         ItemsSource="{Binding SelectorEventosViewModel.SelectorEvents}"
         DisplayMemberPath="Value"
         SelectedItem="{Binding SelectorEventosViewModel.CurrentSelection}"
         IsSynchronizedWithCurrentItem="True" />

      <ListBox Grid.Column="0"
               Name="EventoListBox"
               FontSize="20"
               Margin="10 10"
               Grid.Row="1"
               HorizontalAlignment="Stretch"
               ItemsSource="{Binding EventFilesViewModel.EventFiles}"
               IsSynchronizedWithCurrentItem="True"
               DisplayMemberPath="Value" />
   </Grid>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
   public MainWindow()
   {
      InitializeComponent();
      DataContext = new MainWindowVm();
   }
}

Все вместе, это позволяет вам определять статические значения для вашего исходного комбинированного списка в выделенном фрагменте кода и обновлять источник элементов списка.

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