How to enter data to datagrid wpf with lookup product size base on product

Montri Anthony 21 Reputation points
2021-09-25T13:29:21.46+00:00

I've seen Q&A in https://learn.microsoft.com/en-us/answers/questions/34099/datagridtemplatecomboboxcolumn-in-wpf.html

Then I've question about how to enter products and sizes on Datagird via Combobox or any help users to fill it.
EX

Product Shirt size 10, 11, 12, 13, 14,
Product Paint size 10x12 ,10x13, 10x14
Product Shoe size 44,45,46

when user enter Gird first select Product on Combobox Product then Combobox Size Base on that Product Populate and user select it.

I've try many ways base on your example about still can't do it, pls advise

by the way i've followed mvvm.

using System;  
using System.Collections.Generic;  
using System.Collections.ObjectModel;  
using System.ComponentModel;  
using System.Diagnostics;  
using System.Linq;  
using System.Runtime.CompilerServices;  
using System.Text;  
using System.Windows.Data;  
  
namespace TestGrid3  
{  
    class ViewModel : INotifyPropertyChanged  
    {  
        // ctor to fill demo data  
        public ViewModel()  
        {  
            Random rnd = new Random();  
  
            // Lookup data (display list in ComboBox)  
            ObservableCollection<Product> colProduct = new ObservableCollection<Product>();  
            for (int i = 1; i < 10; i++)   
                colProduct.Add(new Product { ID = i, Text = $"Product-Text {i}" });  
            cvsProduct.Source = colProduct;  
  
            // Lookup all Size  
            ObservableCollection<ProductSize> colAllSize = new ObservableCollection<ProductSize>();  
            for (int i = 1; i < 30; i++)   
            {  
                int id = rnd.Next(1, 6);  
                colAllSize.Add(new ProductSize { ID = id, Size = "Size " + id, Price = rnd.Next(100, 1000) });  
            }  
            cvsAllSize.Source = colAllSize;  
  
                         
            // data objects (DataGrid rows)==========  
            ObservableCollection<ProductOrder> colData = new ObservableCollection<ProductOrder>();  
            for (int i = 1; i < 10; i++)   
                colData.Add(new ProductOrder { IDInv = i, Info = $"Row {i}", IDProduct = rnd.Next(1, 5 + 1),IDSize = rnd.Next(1,20) });  
            cvsData.Source = colData;  
  
            foreach(ProductOrder a in colData)  
            {  
                Debug.WriteLine(a.IDInv+" "+ a.Info+" "+ a.IDProduct+" "+ a.IDSize);  
            }  
  
              
            cvsData.View.CurrentChanged += (sender, e) =>   
                {   
                    SelectedObject = cvsData.View.CurrentItem;  
                    ProductOrder d = (ProductOrder)cvsData.View.CurrentItem;  
                    int sizeId = 0;  
                    if (d != null)  
                    {  
                        sizeId = d.IDProduct;  
                    }  
                    var enuSize = colAllSize.Where(x => x.ID == sizeId);  
                    //ColLookupSize = colAllSize.Where(x => x.ID == sizeId);  
                      
                    ColLookupSize = new ObservableCollection<ProductSize>(enuSize);  
                      
                    //cvsSelectedSize.Source = colLookupSize;  
                      
                };  
            cvsData.View.MoveCurrentToPosition(-1);  
            cvsData.View.MoveCurrentToFirst();  
        }  
  
        // DataGrid view  
        private CollectionViewSource cvsData = new CollectionViewSource();  
        public ICollectionView ViewData { get { return cvsData.View; } }  
  
        // ComboBox view  
        private CollectionViewSource cvsProduct = new CollectionViewSource();  
        public ICollectionView ViewProduct { get { return cvsProduct.View; } }  
  
        // Combo Size view  
        private CollectionViewSource cvsAllSize = new CollectionViewSource();  
        public ICollectionView ViewAllSizeLookup { get { return cvsAllSize.View; } }  
  
        // Lookup Selected Size  
        private ObservableCollection<ProductSize> colLookupSize;  
        public ObservableCollection<ProductSize> ColLookupSize  
        {  
            get => colLookupSize;  
            set  
            {  
                colLookupSize = value;  
                OnPropertyChanged();  
            }  
        }  
        // Combo Search Size view  
        private CollectionViewSource cvsSelectedSize = new CollectionViewSource();  
        public ICollectionView ViewSelectedSizeLookup { get { return cvsSelectedSize.View; } }  
  
        // for Detail display and edit  
        private object _selectedObject = null;  
        public object SelectedObject  
        {  
            get => this._selectedObject;  
            set { this._selectedObject = value; OnPropertyChanged(); }  
        }  
        public event PropertyChangedEventHandler PropertyChanged;  
        private void OnPropertyChanged([CallerMemberName] string propName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));  
  
    }  
  
    // DataGrid data itemOrder  
    public class ProductOrder   
    {  
        public int IDInv { get; set; }  
        public string Info { get; set; }  
        public int IDProduct { get; set; } // foreign key value  
        public int IDSize { get; set; } // forreign key id size  
          
        //public string Price { get; set; }  
  
    }  
  
    // ComboBox list data (lookup data)  
    public class Product  
    {  
        public int ID { get; set; } // Key value  
        public string Text { get; set; } // text to display in DataGrid (ComboBoxColumn)  
    }  
  
   
  
    public class ProductSize  
    {  
        public int ID { get; set; }  
        public string Size { get; set; }  
        public int Price { get; set; }  
    }  
}  

xml

<Window x:Class="TestGrid3.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:TestGrid3"  
        mc:Ignorable="d"  
        Title="MainWindow" Height="450" Width="800">  
  
    <Window.Resources>  
        <local:ViewModel x:Key="vm"/>  
    </Window.Resources>  
  
    <Grid DataContext="{StaticResource vm}">  
        <Grid.ColumnDefinitions>  
            <ColumnDefinition/>  
            <ColumnDefinition/>  
        </Grid.ColumnDefinitions>  
        <DataGrid ItemsSource="{Binding ViewData}"   
                   AutoGenerateColumns="False"   
                   IsReadOnly="False">  
            <DataGrid.Columns>  
                <DataGridTextColumn Header="ID"   
                                 Binding="{Binding IDInv}"/>  
                <DataGridTextColumn Header="Info"   
                                 Binding="{Binding Info}"/>  
                <DataGridComboBoxColumn Header="Product"  
                                     ItemsSource="{Binding ViewProduct, Source={StaticResource vm}}"  
                                     DisplayMemberPath="Text"  
                                     SelectedValuePath="ID"  
                                     SelectedValueBinding="{Binding IDProduct}"/>  
                <DataGridComboBoxColumn Header="LookUp 2"  
                                     ItemsSource="{Binding ColLookupSize, Source={StaticResource vm}}"  
                                     DisplayMemberPath="Size"  
                                     SelectedValuePath="ID"  
                                     SelectedValueBinding="{Binding IDSize}"/>  
            </DataGrid.Columns>  
        </DataGrid>  
        <Grid Grid.Column="1"  
               DataContext="{Binding SelectedObject}">  
            <Grid.ColumnDefinitions>  
                <ColumnDefinition/>  
                <ColumnDefinition/>  
            </Grid.ColumnDefinitions>  
            <Grid.RowDefinitions>  
                <RowDefinition Height="Auto"/>  
                <RowDefinition Height="Auto"/>  
                <RowDefinition Height="Auto"/>  
                <RowDefinition Height="Auto"/>  
                <RowDefinition Height="Auto"/>  
                <RowDefinition Height="Auto"/>  
                <RowDefinition/>  
            </Grid.RowDefinitions>  
            <Grid.Resources>  
                <Style TargetType="Label">  
                    <Setter Property="HorizontalAlignment" Value="Right"/>  
                    <Setter Property="Margin" Value="5"/>  
                </Style>  
                <Style TargetType="TextBox">  
                    <Setter Property="Margin" Value="5"/>  
                </Style>  
                <Style TargetType="ComboBox">  
                    <Setter Property="Margin" Value="5"/>  
                </Style>  
            </Grid.Resources>  
            <Label Content="Details"/>  
  
            <Label Grid.Row="1" Grid.Column="0" Content="IDInv"/>  
            <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding IDInv}" IsReadOnly="True"/>  
  
            <Label Grid.Row="2" Grid.Column="0" Content="Info"/>  
            <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Info}"/>  
  
            <Label Grid.Row="3" Grid.Column="0" Content="Product"/>  
            <ComboBox Grid.Row="3" Grid.Column="1"   
                     ItemsSource="{Binding ViewProduct, Source={StaticResource vm}}"  
                                     DisplayMemberPath="Text"  
                                     SelectedValuePath="ID"  
                                     SelectedValue="{Binding IDProduct}"/>  
              
            <Label Grid.Row="4" Grid.Column="0" Content="Lookup 1"/>  
            <ComboBox Grid.Row="4" Grid.Column="2"   
                     ItemsSource="{Binding ColLookupSize, Source={StaticResource vm}}"  
                                     DisplayMemberPath="Size"  
                                     SelectedValuePath="ID"  
                                     SelectedValue="{Binding IDSize}"/>  
        </Grid>  
    </Grid>  
</Win  
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,807 questions
{count} votes

Accepted answer
  1. Hui Liu-MSFT 48,596 Reputation points Microsoft Vendor
    2021-10-07T10:00:42.063+00:00

    For a one-to-many relationship, we take a collection of one class as an property of another class. The following is an example of binding a DataGrid to a one-to-many relationship model. You could try to refer to it.

    <Grid>  
            <DataGrid ItemsSource="{Binding Source}" Width="800">  
                <DataGrid.Columns>  
                    <DataGridTemplateColumn Header="main" Width="100">  
                        <DataGridTemplateColumn.CellTemplate>  
                            <DataTemplate>  
                                <TextBlock Width="150"  Text="{Binding SelectedName}" />  
                            </DataTemplate>  
                        </DataGridTemplateColumn.CellTemplate>  
                        <DataGridTemplateColumn.CellEditingTemplate>  
                            <DataTemplate>  
                                <ComboBox Width="190"  SelectedValuePath="Name"                        
                                      SelectedValue="{Binding SelectedName}"                                    
                                      SelectedItem="{Binding SelectedMainItem, UpdateSourceTrigger=PropertyChanged}"                        
                                      DisplayMemberPath="Name"                        
                                      ItemsSource="{Binding SomeBinding}"/>  
                            </DataTemplate>  
                        </DataGridTemplateColumn.CellEditingTemplate>  
                    </DataGridTemplateColumn>  
                    <DataGridTemplateColumn Header="sub" Width="100">  
                        <DataGridTemplateColumn.CellTemplate>  
                            <DataTemplate>  
                                <TextBlock  Width="150" Text="{Binding SelectedSubitem}" />  
                            </DataTemplate>  
                        </DataGridTemplateColumn.CellTemplate>  
                        <DataGridTemplateColumn.CellEditingTemplate>  
                            <DataTemplate>  
                                <ComboBox SelectedValue="{Binding SelectedSubitem}"                        
                                      ItemsSource="{Binding  Path=SelectedMainItem.Subitems}" />  
                            </DataTemplate>  
                        </DataGridTemplateColumn.CellEditingTemplate>  
                    </DataGridTemplateColumn>  
                </DataGrid.Columns>  
            </DataGrid>  
        </Grid>  
    

    The code of xaml:

    using System.Collections.Generic;  
    using System.ComponentModel;  
    using System.Windows;  
    namespace WpfApp3  
    {  
      public partial class MainWindow : Window  
      {  
        public MainWindow()  
        {  
          InitializeComponent();  
          DataContext = new VMColl();  
        }  
      }  
      public class VMColl  
      {  
        List<VM> source;  
    
        public List<VM> Source  
        {  
          get { return source; }  
          set { source = value; }  
        }  
    
        public VMColl()  
        {  
          source = new List<VM>() { new VM(), new VM(), new VM(), new VM() };  
        }  
      }  
      public class VM : Notify  
      {  
        private List<mainObj> _items;  
        public List<mainObj> SomeBinding  
        {  
          get { return _items; }  
          set  
          {  
            _items = value;  
            OnPropertyChanged("Items");  
          }  
        }  
        private string _selectedName;  
        public string SelectedName  
        {  
          get { return _selectedName; }  
          set  
          {  
            _selectedName = value;  
            OnPropertyChanged("SelectedName");  
          }  
        }  
    
        private mainObj _selectedMainItem;  
        public mainObj SelectedMainItem  
        {  
          get { return _selectedMainItem; }  
          set  
          {  
            _selectedMainItem = value;  
            OnPropertyChanged("SelectedMainItem");  
            OnPropertyChanged("SelectedMainItem.Subitems");  
          }  
        }  
    
        private string _selectedSubitem;  
        public string SelectedSubitem  
        {  
          get { return _selectedSubitem; }  
          set  
          {  
            _selectedSubitem = value;  
            OnPropertyChanged("SelectedSubitem");  
          }  
        }  
        public VM()  
        {  
          SomeBinding = new List<mainObj>() { new mainObj("first"), new mainObj("second"), new mainObj("someother") };  
        }  
      }  
      public class mainObj : Notify  
      {  
        private BindingList<string> _subitems;  
        public BindingList<string> Subitems  
        {  
          get { return _subitems; }  
          set  
          {  
            _subitems = value;  
            OnPropertyChanged("Subitems");  
          }  
        }  
        private string _name;  
        public string Name  
        {  
          get { return _name; }  
          set  
          {  
            _name = value;  
            OnPropertyChanged("Name");  
          }  
        }  
        public mainObj(string name)  
        {  
          _name = name;  
          _subitems = new BindingList<string>() { "1", "2", "3" };  
        }  
        public override string ToString()  
        {  
          return Name;  
        }  
      }  
      public class Notify : INotifyPropertyChanged  
      {  
        public event PropertyChangedEventHandler PropertyChanged;  
        protected void OnPropertyChanged(string name)  
        {  
          PropertyChangedEventHandler handler = PropertyChanged;  
          if (handler != null)  
          {  
            handler(this, new PropertyChangedEventArgs(name));  
          }  
        }  
      }  
    }  
    

    The picture of result:
    138438-8.gif


    If the response is helpful, please click "Accept Answer" and upvote it.
     Note: Please follow the steps in our [documentation][5] to enable e-mail notifications if you want to receive the related email notification for this thread. 

    [5]: https://learn.microsoft.com/en-us/answers/articles/67444/email-notifications.html


2 additional answers

Sort by: Most helpful
  1. Montri Anthony 21 Reputation points
    2021-10-03T04:17:08.603+00:00

    @Hui Liu-MSFT

    i've sent some code that I understood pls correct if i do wrong understand

    XML

    <Window.Resources>  
            <local:ViewModel x:Key="vm"/>  
      
        </Window.Resources>  
        <Grid>  
            <DataGrid ItemsSource="{Binding ListSaleProduct}" AutoGenerateColumns="False">  
                <DataGrid.Columns>  
                    <DataGridTextColumn Header="INV-ID" Binding="{Binding ID}"/>  
                    <DataGridTemplateColumn>  
                        <DataGridTemplateColumn.CellTemplate>  
                            <DataTemplate>  
                                <ComboBox ItemsSource="{Binding ListProduct,Source={StaticResource vm}}"  
                                          DisplayMemberPath="Name" SelectedValuePath="ID"  
                                          SelectedValue="{Binding ProductID}"  
                                          SelectedItem="{Binding SelectedProduct,Source={StaticResource vm}}"/>  
                            </DataTemplate>  
                        </DataGridTemplateColumn.CellTemplate>  
                    </DataGridTemplateColumn>  
                      
                    <DataGridTemplateColumn>  
                          
                        <DataGridTemplateColumn.CellTemplate>  
                            <DataTemplate>  
                                <ComboBox ItemsSource="{Binding cmbProduct,Source={StaticResource vm}}"  
                                          DisplayMemberPath="Size" SelectedValuePath="IDSize"  
                                          SelectedValue="{Binding SizeID}"  
                                          />  
                            </DataTemplate>  
                        </DataGridTemplateColumn.CellTemplate>  
                    </DataGridTemplateColumn>  
      
                </DataGrid.Columns>  
            </DataGrid>  
        </Grid>  
    

    View Model

    public class ViewModel : INotifyPropertyChanged  
        {  
            public event PropertyChangedEventHandler PropertyChanged;  
            public IList<Product> ListProduct { get; set; }  
            public IList<ProductDetail> ListProductDetail { get; set; }  
            public ICollection<ProductDetail> cmbProduct { get; set; }  
            public ObservableCollection<ProductSale> ListSaleProduct { get; set; }  
      
            public ViewModel()   
            {  
                ListProduct = new List<Product>  
                {  
                    new Product(){ID=1,Name="Shirt"},  
                    new Product(){ID=2,Name="Paint"},  
                    new Product(){ID=3,Name="Shoe"}  
                };  
      
                ListProductDetail = new List<ProductDetail>  
                {   
                    new ProductDetail(){ID=500,IDProduct=1,IDSize=60,Size="Size 40",Price=200},  
                    new ProductDetail(){ID=500,IDProduct=1,IDSize=61,Size="Size 42",Price=250},  
                    new ProductDetail(){ID=500,IDProduct=1,IDSize=62,Size="Size 44",Price=260},  
                    new ProductDetail(){ID=600,IDProduct=2,IDSize=70,Size="Szie 12x20",Price=40}  
                };  
      
                //usually get from db  
                ListSaleProduct = new ObservableCollection<ProductSale>  
                {  
                    new ProductSale(){ID=100,ProductID=1,SizeID=62},  
                    new ProductSale(){ID=200,ProductID=2,SizeID=70}  
                };  
            }  
      
            private Product _selectedProduct;  
            public Product SelectedProduct  
            {  
                get => _selectedProduct;  
                set  
                {  
                    _selectedProduct = value;  
                    int p_id = _selectedProduct.ID;  
                    cmbProduct = ListProductDetail.Where(s => s.IDProduct == p_id).ToList();  
                    OnPropertyChanged("cmbProduct");  
                }  
            }  
      
            private void OnPropertyChanged(string name)  
            {  
                PropertyChangedEventHandler handler = PropertyChanged;  
                if (handler != null)  
                    handler(this, new PropertyChangedEventArgs(name));  
            }  
      
      
      
      
        }  
          
      
        public class Product  
        {  
            public int ID { get; set; }  
            public string Name { get; set; }  
      
        }  
      
        public class ProductDetail  
        {  
            public int ID { get; set; }  
            public int IDProduct { get; set; }  
            public int IDSize {get;set;}  
            public string Size { get; set; }  
            public int Price { get; set; }  
        }  
      
        public class ProductSale  
        {  
            public int ID { get; set; }  
            public int ProductID { get; set; }  
            public int SizeID { get; set; }  
              
        }  
             
      
    }  
    
    0 comments No comments

  2. Montri Anthony 21 Reputation points
    2021-10-08T13:18:27.933+00:00

    Thank you so much @Hui Liu-MSFT

    Can u please give me a little bit if i need to store & get data from db.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.