I am trying to have a combobox reflect the changes in the underlying viewmodel when this item updates, I have tried to follow the MVVM approach and using INotifypropertyChanged
but no matter what I try I am missing something to have this happen.
I am pretty sure I have the DataContext
correct - the PropertyChanged
event fires, the collection is populated from my DAL, I have tried specifying the SourceUpdateTrigger
in the xaml for the combobox - I just cant figure where the break in the wiring is. Your help would be greatly appreciated, happy for direction to usual examples too.
XAML for combobox
<ComboBox ItemsSource="{Binding partsResultsCollection}" x:Name="searchInput" TextBoxBase.TextChanged="searchInput_TextChanged" HorizontalAlignment="Left" Margin="231,88,0,0" VerticalAlignment="Top" Width="316" Height="25" IsEditable="True">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock FontWeight="Bold" Text="PartNO:"/>
<TextBlock Text="{Binding Path=PartNumber}" Padding="10,0"/>
<TextBlock FontWeight="Bold" Text="DESC:"/>
<TextBlock Text="{Binding Path=Description}" Padding="10,0"/>
<TextBlock FontWeight="Bold" Text="QOH:"/>
<TextBlock Text="{Binding Path=QtyOnHand}" Padding="10,0"/>
<TextBlock FontWeight="Bold" Text="WHQ:"/>
<TextBlock Text="{Binding Path=WarehouseQTY}" Padding="10,0"/>
<TextBlock FontWeight="Bold" Text="LastSold:"/>
<TextBlock Text="{Binding Path=LastSold}" Padding="10,0"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
ViewModel Class
class PartsResultsVM : INotifyPropertyChanged
{
public ObservableCollection<PartsResults> _partsResultsCollection;
private PartsResults _singularPartResult;
public PartsDAL partsDAL = new PartsDAL();
public ObservableCollection<PartsResults> partsResultsCollection
{
get { return _partsResultsCollection; }
set {
if (partsResultsCollection != value)
_partsResultsCollection = value;
OnPropertyChanged("partsResultCollection");
}
}
public PartsResults singularPartResult
{
get { return _singularPartResult; }
set {
if (singularPartResult != value)
{
_singularPartResult = value;
OnPropertyChanged("singularPart");
}
_singularPartResult = value; }
}
public PartsResultsVM()
{
_partsResultsCollection = new ObservableCollection<PartsResults>();
}
public void Update(String Query)
{
_partsResultsCollection.Clear();
_partsResultsCollection = partsDAL.getPartListing(Query);
OnPropertyChanged("Update");
Debug.WriteLine("partresultcollection contains:" _partsResultsCollection.Count " Items");
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
Debug.WriteLine("PropertyChanged event fired info " info);
}
}
The Page containing the combobox
public partial class PartsManagement : Page
{
private String connectionString;
private PartsResultsVM partsResultsVM;
public PartsManagement()
{
InitializeComponent();
connectionString = @"Provider = Microsoft.ACE.OLEDB.12.0; Data Source = C:\Register\SourceCode\DataBase\Medicar.mdb";
partsResultsVM = new PartsResultsVM();
this.DataContext = partsResultsVM;
}
private void searchInput_TextChanged(object sender, TextChangedEventArgs e)
{
partsResultsVM.Update(searchInput.Text);
}
}
Adding partresult model class
public class PartsResults
{
private string partNumber;
private string description;
private int qtyOnHand;
private int warehouseQTY;
private DateTime lastSupplied;
public string PartNumber
{
get {return partNumber;}
set
{
partNumber = value;
//this.RaisePropertyChanged("Partnumber");
}
}
public string Description
{
get {return description;}
set
{
description = value;
//this.RaisePropertyChanged("Description");
}
}
public int QtyOnHand
{
get{return qtyOnHand;}
set
{
qtyOnHand = value;
// this.RaisePropertyChanged("QtyOnHand");
}
}
public int WarehouseQTY
{
get{return warehouseQTY;}
set
{
warehouseQTY = value;
//this.RaisePropertyChanged("WarehouseQTY");
}
}
public DateTime LastSupplied
{
get { return lastSupplied; }
set
{
lastSupplied = value;
// this.RaisePropertyChanged("LastSupplied");
}
}
}
CodePudding user response:
I think I understand the problem. You need the ICollectionView
interface to display the data. Here you can find more detailed information.
Apply the following changes in the ViewModel.
public ICollectionView partsResultsCollectionView { get; private set; }
public ObservableCollection<PartsResults> partsResultsCollection = new ObservableCollection<PartsResults>();
public PartsResultsVM()
{
partsResultsCollectionView = CollectionViewSource.GetDefaultView(partsResultsCollection);
partsResultsCollection.Add(new PartsResults { PartNumber = "PartNumber1", Description = "Description1", LastSold = "LastSold1", QtyOnHand = "QtyOnHand1", WarehouseQTY = "WarehouseQTY1" });
}
If you want to make changes in a previously added PartResults element. You should implement INotifyPropertyChanged for each item.
Note : I didn't see you add the PartResults class. So I assumed they were all strings. You fix it :)
CodePudding user response:
So it appears that the issue was with the assigning of the results from the DAL here
_partsResultsCollection = partsDAL.getPartListing(Query);
which does not fire a "ObservableCollection.CollectionChanged Event"
the ObservableCollection bound to the combobox did not notify of changes
when updating the ObservableCollection as follows
results = partsDAL.getPartListing(Query);
foreach (PartsResults partsResults in results)
{
_partsResultsCollection.Add(partsResults);
}
with no other modifications the combobox populated as expected.