Sam White
Sam White

Reputation: 138

ComboBox to show only unique values of a field in an ICollectionView

I have a DataGrid with its ItemSource bound to an ICollectionView (for filtering). I'm trying to have a ComboBox which will filter the EffectiveDate column in the DataGid, its ItemsSource (dropdown values) should be the EffectiveDate of all currently available rows (there are other filters too) in the DataGrid.

Here's the code:

In the MainWindow:

<DataGrid Name="ProductsList"
          ItemsSource="{Binding PricesView}" AutoGenerateColumns="False">
    <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Sku}" Header="Sku"/>
            <DataGridTextColumn Binding="{Binding Upc}" Header="UPC"/>
            <DataGridTextColumn Binding="{Binding Cost}" Header="Cost"/>
            <DataGridTextColumn Binding="{Binding Map}" Header="MAP"/>
            <DataGridTextColumn Binding="{Binding List.EffectiveDate, StringFormat=d}" Header="List Effective Date"/>
            <DataGridTextColumn Binding="{Binding List.Vendor.Name}" Header="Vendor"/>
    </DataGrid.Columns>
</DataGrid>

<ComboBox ItemsSource="{Binding PricesView}" DisplayMemberPath="List.EffectiveDate"/>

In the MainWIndowViewModel:

public ICollectionView PricesView { get; set; }

public ObservableCollection<Price> Prices { get; set; } = new ObservableCollection<Price>(DataAccess.GetVendorPricing());

public MainWIndowViewModel()
{
    PricesView = CollectionViewSource.GetDefaultView(Prices);
}

Price Class:

public class Price
    {
        public int Id { get; set; }
        public PriceList List { get; set; }
        public string Sku { get; set; }
        public string Description { get; set; }
        public string Upc { get; set; }
        public double Cost { get; set; }
        public double Map { get; set; }
    }

List above is of type PriceList: (Here's where you find the EffectiveDate property)

  public class PriceList
    {
        public int Id { get; set; }
        public Vendor Vendor { get; set; }
        public string FileName { get; set; }
        public DateTime EffectiveDate { get; set; }
    }

The issue is that the ComboBox brings up the EffecitveDate for each row (thousands of them!), what I need is just the unique values.

I tried this method, using an IValueConverter, the problem is that converter takes in the entire ICollectionView without the DisplayMemberPath and returns distinct values of the entire collection (which is basically everything), what I'm after is distinct values of only this specific field.

How can I have the ComboBox only show unique values of EffectiveDate?

Upvotes: 0

Views: 1400

Answers (2)

use distinc in sql when you load the data from reader

using (SqlConnection conn = new SqlConnection("Your Connectionstring"))
            {
                conn.Open();
                SqlCommand cmd = new SqlCommand("Your select Query", conn);

                SqlDataReader dr = cmd.ExecuteReader();

                IList<string> listName = new List<string>();
                while (dr.Read())
                {
                    listName.Add(dr[0].ToString());
                }
                listName = listName.Distinct().ToList();
                ComboBox1.DataSource = listName;
            }</string></string>

Upvotes: 0

Formentz
Formentz

Reputation: 1193

Are your records immutable? If so, you could publish a property on the ViewModel to obtain the distinct grouped values using Linq:

    public IEnumerable<DateTime> DistinctDates
    {
        get
        {
            return from item in this.PricesView.Cast<Price>()
                   group item by item.List.EffectiveDate into g
                   select g.Key;
        }
    }

<ComboBox ItemsSource="{Binding DistinctDates}" />

If the data can be edited it is more difficult and you should notify the "DistinctDate" property change or search for another method...

Upvotes: 1

Related Questions