GridView 视觉上不显示 BindingList 中的新数据

GridView visually not showing new data in BindingList

我不熟悉将 MVVM 与 WPF 结合使用,但遇到了障碍。我有一个 BindingList 绑定到 GridView 上的 ItemsSource。我添加了一个按钮,它使用 RelayCommand 从数据库中提取新数据并将其存储在 BindingList 中。调试时我可以在 BindingList 中看到新项目,但在视觉上它没有显示在网格中。这让我很吃力,请看下面我的代码块:

这是对网格视图的绑定:

ItemsSource="{Binding ListOfAllShipments, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SelectedShipment}"

这是视图模型:

public class EntriesShipmentViewModel : INotifyPropertyChanged
{
   public EntriesShipmentViewModel()
   {
      GetAllShipments();
      RefreshGridViewsCommand = new RelayCommand(GetAllShipments);
   }

   private BindingList<Shipment> _listOfAllShipments;
   private BindingList<Shipment> _listOfAssignedShipments;

   #region Private Properties

   private Shipment _selectedShipment;
   private string _manifestNumber;
   private string _carrier;
   private string _localShippingAgent;
   private string _voyageNumber;
   private string _shipmentKey;

   #endregion

   #region Public Properties

   public Shipment SelectedShipment
   {
      get => _selectedShipment;
      set
      {
         if (value == null)
            return;

         _selectedShipment = value;
         OnPropertyRaised(SelectedShipment.ToString());
         PopulateManifestInformation(SelectedShipment);
      }
   }

   public string ManifestNumber
   {
      get => _manifestNumber;
      set
      {
         _manifestNumber = value;
         OnPropertyRaised(ManifestNumber);
         OnPropertyRaised(nameof(ManifestNumber));
      }
   }

   public string Carrier
   {
      get => _carrier;
      set
      {
         _carrier = value;
         OnPropertyRaised(Carrier);
         OnPropertyRaised(nameof(Carrier));
      }
   }

   public string LocalShippingAgent
   {
      get => _localShippingAgent;
      set
      {
         _localShippingAgent = value;
         OnPropertyRaised(LocalShippingAgent);
         OnPropertyRaised(nameof(LocalShippingAgent));
      }
   }

   public string VoyageNumber
   {
      get => _voyageNumber;
      set
      {
         _voyageNumber = value;
         OnPropertyRaised(VoyageNumber);
         OnPropertyRaised(nameof(VoyageNumber));
      }
   }

   public string ShipmentKey
   {
      get => _shipmentKey;
      set
      {
         _shipmentKey = value;
         OnPropertyRaised(ShipmentKey);
         OnPropertyRaised(nameof(ShipmentKey));
      }
   }

   #endregion

   public ICommand RefreshGridViewsCommand { get; }

   private void GetAllShipments()
   {
      ListOfAllShipments = ShipmentViewModel.GetAllShipments();

      if (SelectedShipment != null)
      {
         SelectedShipment = null;
      }
   }

   public BindingList<Shipment> ListOfAllShipments
   {
      get => _listOfAllShipments;
      set
      {
         _listOfAllShipments = value;

      }
   }

   private void PopulateManifestInformation(Shipment shipment)
   {
      if (shipment == null)
         return;

      if (shipment.MasterManifest != null)
      {
         ManifestNumber = shipment.MasterManifest.Number;
         if (shipment.MasterManifest.IsMasterManifest && shipment.MasterManifest.Voyage != null)
         {
            Carrier = shipment.MasterManifest.Voyage.Carrier.Name;
            LocalShippingAgent = shipment.MasterManifest.LocalShippingAgent.Name;
            VoyageNumber = shipment.MasterManifest.Voyage.DisplayName;
         }

      }
      else if (shipment.SupplementaryManifest != null)
      {
         ManifestNumber = shipment.SupplementaryManifest.Number;
         if (shipment.SupplementaryManifest.IsMasterManifest && shipment.SupplementaryManifest.Voyage != null)
         {
            Carrier = shipment.SupplementaryManifest.Voyage.Carrier.Name;
            LocalShippingAgent = shipment.SupplementaryManifest.LocalShippingAgent.Name;
            VoyageNumber = shipment.SupplementaryManifest.Voyage.DisplayName;
         }

      }

      ShipmentKey = shipment.Id.ToString();
      }

   public event PropertyChangedEventHandler PropertyChanged;

   private void OnPropertyRaised(string propertyname)
   {
      if (PropertyChanged != null)
      {
         PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
      }
   }
}

问题是您创建了一个新集合并将其分配给 ListOfAllShipments 属性:

ListOfAllShipments =  ShipmentViewModel.GetAllShipments();

但是,您没有在 setter 中引发 PropertyChanged 事件,因此绑定不会更新。

public BindingList<Shipment> ListOfAllShipments
{
   get => _listOfAllShipments;
   set
   {
      _listOfAllShipments = value;
      OnPropertyRaised(nameof(ListOfAllShipments));
   }    
}

另一种方法是始终使用相同的集合,但只需在 GetAllShipments 方法中使用 Clear() or ClearItems() 清除它并添加新项目。 BindingList.

会自动通知这些更改

为了完整起见,对您的代码进行一些说明。

  • 您可以从 ItemsSource 绑定中删除 UpdateSourceTrigger

  • OnPropertyRaised 调用得到一个 属性 name 作为参数,所以像这样使用 nameof 是可以的:

    OnPropertyRaised(nameof(ShipmentKey));
    

    但是,我认为像下面这样的重复调用没有意义,因为您传递了 属性 值 。因此,您应该能够毫无区别地删除它们。

    PropertyRaised(ShipmentKey);