Home > OS >  How do I display a different list than the source item when opening the combo box?
How do I display a different list than the source item when opening the combo box?

Time:08-30

I'm using C# WPF with a SQL Server database. I have DataGrid that filled by Factor table from database (ItemSource).

Inside of this DataGrid, I have a combobox that is also filled with different table as Commodity that is related to Factor.

enter image description here

What I need

I want the combobox I have to be filled with a list from my Commodity table, but what is selected as the value is from the data grid (from the value filled in each row).

What have I tried

XAML:

    <Window x:Class="ComboDataWPF.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:ComboDataWPF"
            mc:Ignorable="d"
            x:Name="InvoiceWindow"
            Title="MainWindow" Height="450" Width="800" WindowStartupLocation="CenterScreen" Loaded="Window_Loaded">
        
        <Grid>
            <DataGrid x:Name="MainDataGrid" AutoGenerateColumns="False" ItemsSource="{Binding WHOLE_DATA_FACTOR, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Customer Name" Width="120" Binding="{Binding CustomerName, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" />
    
                    <DataGridTemplateColumn Header="The Product Customer Bought" Width="200">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox x:Name="ComboBox_Commodity"
                                          ItemsSource="{Binding ElementName=InvoiceWindow ,Path=TheCommodityCombo_DATA}"
                                          DisplayMemberPath="CommodityName"
                                          SelectedValuePath="CommodityCode"
                                          IsTextSearchEnabled="True"
                                          IsEditable="True"
                                          SelectedIndex="0"  BorderBrush="#FFADEEB4" Background="{x:Null}" BorderThickness="1">
                                    
                                    <!--For ComboBox_Commodity ↑-->
                                    <!--SelectedValue="{Binding The selected value of each combo box is proportional and based on the value of that row in the datagrid}"-->
                                    <ComboBox.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <VirtualizingStackPanel VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling"/>
                                        </ItemsPanelTemplate>
                                    </ComboBox.ItemsPanel>
                                </ComboBox>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
    
                </DataGrid.Columns>
    
            </DataGrid>
        </Grid>
    </Window>

Code-behind:

    public partial class MainWindow : Window
    {
        MyerEntities dbms = new MyerEntities();

        /// <summary>
        /// For Factor Table
        /// </summary>
        public class MyCustomModel_Factor
        {
            public long? NUMBER { get; set; }
            public string CustomerName { get; set; }
            public long? CommodityCode { get; set; }
        }

        public ObservableCollection<MyCustomModel_Factor> WHOLE_DATA_FACTOR { get; set; } = new ObservableCollection<MyCustomModel_Factor>();
    
        /// <summary>
        /// For Commodity Table for ComboBox Items
        /// </summary>
        public ObservableCollection<MyCustomModel_Commodity> TheCommodityCombo_DATA { get; set; } = new ObservableCollection<MyCustomModel_Commodity>();
        public class MyCustomModel_Commodity
        {
            public long CommodityCode { get; set; }
            public string CommodityName { get; set; }
        }

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //Filling DataGrid by ObservableCollection
            WHOLE_DATA_FACTOR.Clear();
            var RST = dbms.Database.SqlQuery<MyCustomModel_Factor>("SELECT * FROM Factor").ToList();
            foreach (var item in RST)
            { WHOLE_DATA_FACTOR.Add(item); }
    
            //Filling ComboBox from another table that is related to Factor table
            TheCommodityCombo_DATA.Clear();
            var RST2 = dbms.Database.SqlQuery<MyCustomModel_Commodity>("SELECT CommodityCode, CommodityName FROM dbo.Commodity").ToList();

            foreach (var item2 in RST2)
            {
                TheCommodityCombo_DATA.Add(item2);
            }
        }
    }

My source code: https://ufile.io/x4xqe9ti

Similar question but for Winforms: How do I show the display value for a combo box for the bound item?

How can I do that in WPF? Please help

CodePudding user response:

Change the binding to the collection of commodities to use a RelativeSource:

ItemsSource="{Binding Path=TheCommodityCombo_DATA, RelativeSource={RelativeSource AncestorType=Window}}"

Then you should see the values to choose from in the ComboBox.

For the correct value to get selected, you should then bind the SelectedValue property of the ComboBox to the CommodityCode property of the model:

<ComboBox ... SelectedValue="{Binding CommodityCode}"
  • Related