how to define source for wpf datagrid xaml DataGridComboBoxColumn

Babu R 61 Reputation points
2020-05-26T19:12:48.48+00:00

Hai
I am trying to set source for datagrid custom control DataGridComboBoxColumn.
I used code like this

In viewmodel

     public ObservableCollection<MarKList> NameList { get; set; }

 public ViewModel()
        {
            NameList =new ObservableCollection<MarKList>(db.MarKLists.ToList());
        }

in mainwindow

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                ViewModel VM = new ViewModel();
                SubPage Sp = new SubPage();
                Sp.DataContext = VM;
                MainFrame.Content = Sp;
            }

and in page

<local:DataGridUser x:Name="Dg_Student" ItemsSource="{Binding Vm_StudentCollection}"  CurrentItem="{Binding Vm_StudentCollection_Curitem,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"     AutoGenerateColumns="False"  HorizontalAlignment="Left" Height="282" Margin="107,58,0,0" VerticalAlignment="Top" Width="247" SelectionUnit="CellOrRowHeader" SelectionMode="Single">
<local:DataGridUser.Columns>
                    <DataGridTextColumn Header="Name" Binding="{Binding M_Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"  />
                    <DataGridComboBoxColumn  Header="Gender"  ItemsSource="{Binding NameList}" DisplayMemberPath="Name" SelectedItemBinding="{Binding M_Enm_Gender_SelItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  SelectedValuePath="{Binding M_GenderID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="120">
                        <DataGridComboBoxColumn.ElementStyle>
                              <Style TargetType="{x:Type ComboBox}">
                             <Setter Property="ItemsSource" Value="{Binding Path=DataContext.NameList, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
                           </Style>
                        </DataGridComboBoxColumn.ElementStyle>
                        <DataGridComboBoxColumn.EditingElementStyle>
                            <Style TargetType="{x:Type ComboBox}">
                            <Setter Property="ItemsSource" Value="{Binding Path=DataContext.NameList, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
                          <Setter Property="IsEditable" Value="True"/>
                            </Style>
                        </DataGridComboBoxColumn.EditingElementStyle>
                    </DataGridComboBoxColumn>
                    <DataGridTextColumn Header="Mark1" Binding="{Binding M_Mark1, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
                    <DataGridTextColumn Header="Total" Binding="{Binding M_Total, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"  />
                </local:DataGridUser.Columns>

I want to pollute name field from NameList to combo, I tried different methods but none worked. please help what I am doing wrong.
Also I don't want template column.

Thanks

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,667 questions
0 comments No comments
{count} votes

Accepted answer
  1. Alex Li-MSFT 1,096 Reputation points
    2020-05-27T06:59:45.79+00:00

    Welcome to our Microsoft Q&A platform!

    I use the below method to bind the data in the Page.xaml, the DataGridComboBoxColumn can show the namelist.

    1. Add the CollectionViewSource for the page
      <Page.Resources>
                  <CollectionViewSource x:Key="ItemsCVS" Source="{Binding NameList }" />
          </Page.Resources>
      

    2.replace the your ItemsSource="{Binding NameList}" as ItemsSource="{Binding Source={StaticResource ItemsCVS}}" in DataGridComboBoxColumn

    Thanks.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-05-27T06:51:47.37+00:00

    Hi, the documentation on MSDN about the ItemsSource of the DataGridComboBoxColumn says that only static resources, static code or inline collections of combobox items can be bound to the ItemsSource. In your case you can use StaticResource in your XAML:

    <Page x:Class="WpfApp37.SubPage"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          xmlns:local="clr-namespace:WpfApp37"
          mc:Ignorable="d" 
          d:DesignHeight="450" d:DesignWidth="800"
          Title="SubPage">
      <Page.Resources>
        <CollectionViewSource x:Key="GenderList" Source="{Binding NameList}" />
      </Page.Resources>
      <Grid x:Name="grd">
        <local:DataGridUser x:Name="Dg_Student" 
                            ItemsSource="{Binding Vm_StudentCollection}"  
                            CurrentItem="{Binding Vm_StudentCollection_Curitem,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"  
                            AutoGenerateColumns="False"
                            HorizontalAlignment="Left"
                            Height="282"
                            Margin="107,58,0,0" 
                            VerticalAlignment="Top" 
                            Width="247" 
                            SelectionUnit="CellOrRowHeader"
                            SelectionMode="Single">
          <local:DataGridUser.Columns>
            <DataGridTextColumn Header="Name" 
                                Binding="{Binding M_Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"  />
            <DataGridComboBoxColumn Header="Gender"  
                                    ItemsSource="{Binding Source={StaticResource GenderList}}"
                                    DisplayMemberPath="Name" 
                                    SelectedValuePath="ID"
                                    SelectedValueBinding="{Binding M_GenderID}">
            </DataGridComboBoxColumn>
            <DataGridTextColumn Header="Mark1" 
                                Binding="{Binding M_Mark1, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
            <DataGridTextColumn Header="Total" 
                                Binding="{Binding M_Total, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"  />
          </local:DataGridUser.Columns>
        </local:DataGridUser>
      </Grid>
    </Page>
    

    You can test with following code:

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Windows;
    using WpfApp37;
    
    namespace WpfApp1
    {
      public partial class Window37 : Window
      {
        public Window37()
        {
          InitializeComponent();
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
          ViewModel VM = new ViewModel();
          SubPage Sp = new SubPage();
          Sp.DataContext = VM;
          MainFrame.Content = Sp;
        }
      }
    }
    
    namespace WpfApp37
    {
      public class ViewModel
      {
        public ViewModel()
        {
          NameList = new ObservableCollection<MarKList>(db.MarKLists.ToList());
          Vm_StudentCollection = new ObservableCollection<Student>(db.StudentList.ToList());
        }  
        Model db = new Model();
        public ObservableCollection<MarKList> NameList { get; set; }
        public ObservableCollection<Student> Vm_StudentCollection { get; set; }
        public object Vm_StudentCollection_Curitem { get; set; }
      }
    
      public class Student
      {
        public string M_Name { get; set; }
        public int M_GenderID { get; set; }
        public string M_Mark1 { get; set; }
        public int M_Total { get; set; }
      }
    
      public class MarKList
      {
        public string Name { get; set; }
        public int ID { get; set; }
      }
    
      internal class Model
      {
        Random rnd = new Random();
        internal IEnumerable<MarKList> MarKLists
        {
          get
          {
            var l = new List<MarKList>();
            l.Add(new MarKList() { ID = 1, Name = "Male" });
            l.Add(new MarKList() { ID = 2, Name = "Female" });
            l.Add(new MarKList() { ID = 3, Name = "TransGender" });
            return l;
          }
        }
        internal IEnumerable<Student> StudentList { get { for (int i = 0; i < 10; i++) yield return new Student() { M_Name = $"Name {i}", M_GenderID = rnd.Next(1, 4), M_Mark1 = $"Mark1 {i}", M_Total = i }; } }
      }
    }
    

    XAML of MainWindow:

    <Window x:Class="WpfApp1.Window37"
            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:WpfApp1"
            mc:Ignorable="d"
            Title="Window37" Height="450" Width="1000">
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition/>
        </Grid.RowDefinitions>
        <Frame x:Name="MainFrame"
               Grid.Row="1"/>
        <Button Content="Load Page" 
                Width="100" 
                Margin="5" 
                Click="Button_Click"/>
      </Grid>
    </Window>
    
    0 comments No comments