简体   繁体   中英

How to Access the property of Combobox inside of a DataGrid in WPF

I want to Display data in my ComboBox inside of DataGridTemplateColumn in the DataGrid but it's empty in the binding so I decided to fill it in code behind but I couldn't access it by name!

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"
        Title="MainWindow" Height="450" Width="800" WindowStartupLocation="CenterScreen" Loaded="Window_Loaded">
    
    <Grid>
        <DataGrid x:Name="MainDataGrid" AutoGenerateColumns="False" ItemsSource="{Binding ALLMYDATA, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}">

            <DataGrid.Columns>
                <DataGridTextColumn Header="The Name :" Width="120" Binding="{Binding NAMES, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" />

                <DataGridTemplateColumn Header=" Name and Code " Width="150">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox x:Name="ComboBox1"
                                      ItemsSource="{Binding ALLMYDATA, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
                                      SelectedValuePath="{Binding CODE, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
                                      DisplayMemberPath="{Binding NAMES, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
                                      IsTextSearchEnabled="True"
                                      IsEditable="True"
                                      SelectedIndex="0"  BorderBrush="#FFADEEB4" Background="{x:Null}" BorderThickness="1">
                                
                                <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 :

 using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace ComboDataWPF
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            MyerEntities dbms = new MyerEntities();
            public ObservableCollection<MyCustomModel> ALLMYDATA { get; set; } = new ObservableCollection<MyCustomModel>();
            public class MyCustomModel
            {
                public int CODE { get; set; }
                public string NAMES { get; set; }
            }
            public MainWindow()
            {
                InitializeComponent();
                DataContext = this;
            }
            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                ALLMYDATA.Clear();
                var RST = dbms.Database.SqlQuery<MyCustomModel>("SELECT CODE,NAMES FROM TCOD_ANBAR").ToList();
                foreach (var item in RST)
                {
                    ALLMYDATA.Add(item);
                }
            }
        }
    }

my source: https://ufile.io/zvfoj4we

NOTE: I even tried to switch to GridView but it was harder than Datagrid.

so Why the ComboBox is empty and how can I access the property like ItemsSource and... in C#?

Please guide me

I downloaded your source project. And filled ALLMYDATA collection with 2 objects(cuz I don't have DB for it).

private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        ALLMYDATA.Clear();
        MyCustomModel myCustom = new MyCustomModel()
        {
            CODE = 20,
            NAMES = "Yes"
        };
        MyCustomModel myCustom2 = new MyCustomModel()
        {
            CODE = 30,
            NAMES = "No"
        };

        ALLMYDATA.Add(myCustom);
        ALLMYDATA.Add(myCustom2);
    }

So the main problems I saw were in your XAML. As you set DataGrid 's ItemsSource property to ALLMYDATA collection, it is DataContext for all child elements of DataGrid , and when you try to bind ComboBox 's ItemsSource to property like

ItemsSource="{Binding ALLMYDATA, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"

you get the error because DataContext for ComboBox is the ALLMYDATA collection and this collection doesn't contain the ALLMYDATA property, that's why you can't bind to it in ComboBox . So I changed XAML code above to

ItemsSource="{Binding ElementName=MainDataGrid, Path=ItemsSource}"

and it works well as ItemsSource of ComboBox is the same as DataGrid now.

Other problems are related to these pieces of code:

 SelectedValuePath="{Binding CODE, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
DisplayMemberPath="{Binding NAMES, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"

As your ComboBox 's ItemsSource is ALLMYDATA, now you don't need to bind anything just write

SelectedValuePath="CODE"
DisplayMemberPath="NAMES"

Now your ComboBox is not empty:

在此处输入图像描述

Here is the full XAML of your DataGrid

<DataGrid x:Name="MainDataGrid" AutoGenerateColumns="False" ItemsSource="{Binding ALLMYDATA, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}">

        <DataGrid.Columns>
            <DataGridTextColumn Header="The Name :" Width="120" Binding="{Binding NAMES, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" />

            <DataGridTemplateColumn Header=" Name and Code " Width="150">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox x:Name="ComboBox1"
                                  ItemsSource="{Binding ElementName=MainDataGrid, Path=ItemsSource}"
                                  SelectedValuePath="CODE"
                                  DisplayMemberPath="NAMES"
                                  IsTextSearchEnabled="True"
                                  IsEditable="True"
                                  SelectedIndex="0"  BorderBrush="#FFADEEB4" Background="{x:Null}" BorderThickness="1">
                            
                            <ComboBox.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <VirtualizingStackPanel VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling"/>
                                </ItemsPanelTemplate>
                            </ComboBox.ItemsPanel>
                        </ComboBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
    </DataGrid>

You can do it this way.

First, name you Window .

<Window
    :
    x:Name="ThisWindow">

Then bind the ComboBox 's ItemsSource using the Window 's name. Also take a look at the SelectedValuePath and the DisplayMemberPath .

<ComboBox
    x:Name="ComboBox1"
    ItemsSource="{Binding ElementName=ThisWindow, Path=ALLMYDATA, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
    SelectedValuePath="CODE"
    DisplayMemberPath="NAMES"
    IsTextSearchEnabled="True"
    IsEditable="True"
    SelectedIndex="0"
    BorderBrush="#FFADEEB4"
    Background="{x:Null}"
    BorderThickness="1">
    <ComboBox.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling"/>
        </ItemsPanelTemplate>
    </ComboBox.ItemsPanel>
</ComboBox>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM