Im writing a simple wpf application, but Im stuck. I'd like to achieve, that I have a filter class, and If the id has been changed in the filter class by a user input, a list should refresh applying the filter. All the initial bindings are working. The list is displayed properly along with the CompanyId.
the databinding in xaml:
<ListBox Height="212" HorizontalAlignment="Left" Margin="211,31,0,0" Name="listBoxProducts" VerticalAlignment="Top" Width="267" ItemsSource="{Binding ElementName=this, Path=Products}" DisplayMemberPath="CompanyId" />
<TextBox Height="28" HorizontalAlignment="Left" Margin="12,31,0,0" Name="textBoxCompanyId" VerticalAlignment="Top" Width="170" Text="{Binding ElementName=this, Path=Company.Id}" />
The code-behind for the xaml:
private TestFactory _testFactory = new TestFactory();
private Company _company;
public Company Company
{
get { return _company; }
}
private IProductList _products;
public IProductList Products
{
get { return _products; }
}
public MainWindow()
{
_company = _testFactory.Company;
_products = _testFactory.Products;
InitializeComponent();
_company.FilterChanged += _testFactory.FilterChanging;
}
The (dummy)factory class:
private IProductList _products;
public IProductList Products
{
get { return _products; }
}
private Company _company = new Company();
public Company Company
{
get { return _company; }
}
public TestFactory()
{
_company = new Company() { Id = 2, Name = "Test Company" };
GetProducts();
}
public void GetProducts()
{
var products = new List<Product>();
products.Add(new Product() { ProductNumber = 1, CompanyId = 1, Name = "test product 1" });
products.Add(new Product() { ProductNumber = 2, CompanyId = 1, Name = "test product 2" });
products.Add(new Product() { ProductNumber = 3, CompanyId = 2, Name = "test product 3" });
if (Company.Id != 2)
{
products = products.Where(p => p.CompanyId == Company.Id).ToList();
}
_products = new ProductList(products);
}
public void FilterChanging(object sender, EventArgs e)
{
GetProducts();
}
The ProductList interface:
public interface IProductList : IList<Product>, INotifyCollectionChanged {}
The productlist class:
public class ProductList : IProductList
{
private readonly IList<Product> _products;
public ProductList() { }
public ProductList(IList<Product> products)
{
_products = products;
}
public IEnumerator<Product> GetEnumerator()
{
return _products.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(Product item)
{
_products.Add(item);
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
public void Clear()
{
_products.Clear();
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public bool Contains(Product item)
{
return _products.Contains(item);
}
public void CopyTo(Product[] array, int arrayIndex)
{
_products.CopyTo(array, arrayIndex);
}
public bool Remove(Product item)
{
var removed = _products.Remove(item);
if (removed)
{
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
}
return removed;
}
public int Count
{
get { return _products.Count; }
}
public bool IsReadOnly
{
get { return _products.IsReadOnly; }
}
public int IndexOf(Product item)
{
return _products.IndexOf(item);
}
public void Insert(int index, Product item)
{
_products.Insert(index, item);
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void RemoveAt(int index)
{
_products.RemoveAt(index);
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public Product this[int index]
{
get { return _products[index]; }
set
{
_products[index] = value;
notifyCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, _products[index]));
}
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
private void notifyCollectionChanged(NotifyCollectionChangedEventArgs args)
{
if (CollectionChanged != null)
{
CollectionChanged(this, args);
}
}
}
The Company class (filter class):
public class Company : INotifyPropertyChanged
{
private int _id;
public int Id
{
get { return _id; }
set
{
if (_id == value)
return;
_id = value;
OnPropertyChanged("Id");
OnFilterChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
private string _name;
public string Name
{
get { return _name; }
set
{
if (_name == value)
return;
_name = value;
OnPropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler FilterChanged;
private void OnPropertyChanged(string name)
{
if (PropertyChanged == null)
return;
var eventArgs = new PropertyChangedEventArgs(name);
PropertyChanged(this, eventArgs);
}
private void OnFilterChanged(NotifyCollectionChangedEventArgs e)
{
if (FilterChanged == null)
return;
FilterChanged(this, e);
}
}
The list is refreshed in factory, but there is no change in the view. I probably do something wrong, maybe my whole approach is not best. Maybe I have to use ObservableCollection type with valueconverter? Any help would be greatly appreciated. Cheers!
Use an
ObservableCollection<Product>
instead of creating your own list based onIList
The purpose of an
ObservableCollection
is to track changes to the collection, and it will automatically update the UI when the collection changes.