Knowledge2.0
Knowledge2.0

Reputation: 9

Populating a ComboBox from ViewModel or Model in a datagrid

Hello I have a data grid here:

<DataGrid   CanUserResizeRows="False" VerticalAlignment="Top" Margin="0,10,80,0" Grid.Column="0" Grid.RowSpan="3" Grid.ColumnSpan="3" HorizontalAlignment="Center" Grid.Row="1" CanUserAddRows="False" AutoGenerateColumns="False" HeadersVisibility="All">
            <DataGrid.Columns>

                <!-- Combobox-->
                <materialDesign:DataGridComboBoxColumn HeaderStyle="{StaticResource DGHeader}" Header="Part Number"  ItemsSource="{x:Static model:ViewModel.EpicorParts}"/>

                <!--TextBox Column-->
                <materialDesign:DataGridTextColumn HeaderStyle="{StaticResource DGHeader}" Header="Description" Binding="{Binding Description}" ElementStyle="{StaticResource MaterialDesignDataGridTextColumnStyle}" EditingElementStyle="{StaticResource MaterialDesignDataGridTextColumnPopupEditingStyle}"/>

                <!--Combobox Column-->
                <materialDesign:DataGridComboBoxColumn HeaderStyle="{StaticResource DGHeader}" Header="Reason Code"/>

                <materialDesign:DataGridComboBoxColumn HeaderStyle="{StaticResource DGHeader}" Header="Qty"/>

                <!--Numeric Column -->
                <DataGridTemplateColumn Header="BOM" HeaderStyle="{StaticResource DGHeader}" CellTemplate="{StaticResource ButtonColumn}"/>
            </DataGrid.Columns>
        </DataGrid>

So different ObservableCollections populate different areas on here but to start I have a model:

public EpicorParts(SqlDataReader reader)
        {
            Part = reader.GetString("PartNum");
            Desc = reader.GetString("PartDescription");
            partClass = reader.GetString("ClassID");
        }

        private string _Part;
        public string Part
        {
            get { return _Part; }
            set { _Part = value; RaisePropertyChanged("PartNum"); }
        }

        private string _Desc;
        public string Desc
        {
            get { return _Desc; }
            set { _Desc = value; RaisePropertyChanged("PartDescription"); }
        }

        private string _partClass;
        public string partClass
        {
            get { return _partClass; }
            set { _partClass = value; RaisePropertyChanged("ClassID"); }
        }

I would like to populate the part number column with PartNum and the Description column with Desc I've tried using the item source as you see in the combobox column but it doesn't let me nest anymore. Will not let me do ItemsSource="{x:Static model:ViewModel.EpicorParts.Part}"

Just in case this is needed here is the viewmodel

public static ObservableCollection<EpicorParts> EpicorParts { get; set; } = new ObservableCollection<EpicorParts>();

public static void GetEpicorParts()
        {
            EpicorParts.Clear();
            using var conn = new SqlConnection(Settings.Default.Epicor2Connection);

            conn.Open();
            string qry = "SELECT PartNum, PartDescription, ClassID from Erp.part where ClassID='slnc' and InActive = 1";
            var cmd = new SqlCommand(qry, conn);

            var reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                EpicorParts.Add(new EpicorParts(reader));
            }
            conn.Close();
        }

Hopefully I made this clear of what I am trying to do.

Upvotes: 0

Views: 107

Answers (1)

arconaut
arconaut

Reputation: 3285

First, there are some issues with your viewmodel, I believe. You're triggering property change with "PartNum" for two properties. Pay attention to your properties:

public class EpicorPart // or better even EpicorPartViewModel, since you're binding to it
{
    // ...
    public string PartNum
    {
        get { return _part; }
        set { 
            _part = value;
            RaisePropertyChanged(nameof(PartNum)); } // what's used here should match the property name, it's easy to keep this consistent with `nameof()`
        }

    // also, you use 'Desc' here, but 'Description' in the grid...

Next, if I understand the problem correctly, you need to bind the ItemsSource of your DataGrid to the EpicorParts property of your ViewModel.

Each column can then bind to one of the properties of the EpicorPart class:

<DataGrid ItemsSource="{x:Static model:ViewModel.EpicorParts}" >    
   ... columns come here, see below
</DataGrid>

To display the value of 'Part Number' in the combobox column, bind the SelectedItemBinding property to that property of EpicorPart. ItemsSource of DataGridComboBoxColumn is for storing the available options in that combobox (the list you see when the combobox is open). So you should bind it to that list. Not sure if that exists already, but it could look something like this:

<materialDesign:DataGridComboBoxColumn 
    Header="Part Number" 
    SelectedItemBinding="{Binding PartNum}"         ---> this is for what is being displayed as 'selected' in the combobox
    ItemsSource="{Binding AvailablePartNumbers}" /> ---> not sure if you have it, but the point is - it's probably a separate list

<materialDesign:DataGridTextColumn 
    Header="Description" 
    Binding="{Binding Description}"   --> here this should work already, as long as the whole grid is bound to the ObservableCollection
    />

Upvotes: 1

Related Questions