SuperMENG
SuperMENG

Reputation: 439

Not able to bind ObservableCollection to DataGrid

if I write in C# coding it's ok such as

DataGrid dg = new DataGrid();
dg.AutoGenerateColumns = true;
dg.ItemsSource = db;

where db is

public ObservableCollection<Data> db = new ObservableCollection<Data>();

db.Add(new Data { Name = "person1", Description = "sssssss", Price = 15 });
db.Add(new Data { Name = "person2", Description = "okokok", Price = 12 });

it will generate columns and data fine.. but if I write in XAML it can't show any thing

<DataGrid ItemsSource="{Binding db}" AutoGenerateColumns="True"/>

I can't find the way to binding this collection to DataGrid.. please tell me why

this is my all xaml

<Window x:Class="testt.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <StackPanel Orientation="Vertical" Name="Panel">
        <TextBlock Name="count"/>
        <DataGrid ItemsSource="{Binding db}" AutoGenerateColumns="True"/>       
    </StackPanel>
</Grid>
</Window>

thank you

Upvotes: 2

Views: 1220

Answers (6)

SuperMENG
SuperMENG

Reputation: 439

Thank you for your all help now the problem solved!

the db should be property, not field so I change a little code to be

public ObservableCollection<Data> db { set; get; }

and I have to set DataContext with this sentense

this.DataContext = this;

now it can work properly :)

Upvotes: 0

Vimal CK
Vimal CK

Reputation: 3563

You have to Implement INotifyPropertyChanged interface inorder to reflect the changes. Please see the below snippet

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace StylingIntroSample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window,INotifyPropertyChanged
{
    private ObservableCollection<Data> _db = new ObservableCollection<Data>();

    public ObservableCollection<Data> db {
        get { return _db; }
        set
        {
            _db = value;
            OnPropertyChanged("db");
        }
    }

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

    private void LoadItems()
    {
        db.Add(new Data { Name = "person1", Description = "sssssss", Price = 15 });
        db.Add(new Data { Name = "person2", Description = "okokok", Price = 12 });
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string PropertyName)
    {
        if (PropertyChanged!= null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }
    }
}

public class Data
{
    public string Name { get; set; }
    public string Description { get; set; }
    public int Price { get; set; }
}

}

In XAML

<Grid>
    <StackPanel Orientation="Vertical"
                Name="Panel">
        <TextBlock Name="count" />
        <DataGrid Name="MyGrid" ItemsSource="{Binding db}"
                  AutoGenerateColumns="True" />
    </StackPanel>
</Grid>

Upvotes: 0

Rishi_raj
Rishi_raj

Reputation: 85

Try to set the "DisplayMemberPath" for the DataGrid which is the first thing that should be done after setting the DataSource.

Upvotes: 0

Ehsan Hafeez
Ehsan Hafeez

Reputation: 658

You have to set the datacontext of the window to bind the collection with controls under it.

ObservableCollection<Data> db = new ObservableCollection<Data>();

 db.Add(new Data { Name = "person1", Description = "sssssss", Price = 15 });
 db.Add(new Data { Name = "person2", Description = "okokok", Price = 12 });

 this.DataContext = db;

Now in XAML you only set the binding of itemsource.

<DataGrid Name="grdPerson" ItemsSource="{Binding}" AutoGenerateColumns="True"></DataGrid>

Upvotes: 0

Nisarg Chauhan
Nisarg Chauhan

Reputation: 305

If you are not using MVVM,try this in your code,

DataGrid dg = new DataGrid();
dg.AutoGenerateColumns = true;
dg.ItemsSource = db;
this.DataContext = this; //or put this line in constructor.

where db is

public ObservableCollection<Data> db = new ObservableCollection<Data>();

db.Add(new Data { Name = "person1", Description = "sssssss", Price = 15 });
db.Add(new Data { Name = "person2", Description = "okokok", Price = 12 });

And in Xaml,

<Window x:Class="testt.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <StackPanel Orientation="Vertical" Name="Panel">
        <TextBlock Name="count"/>
        <DataGrid ItemsSource="{Binding db}" AutoGenerateColumns="True"/>       
    </StackPanel>
</Grid>
</Window>

Upvotes: 2

DHN
DHN

Reputation: 4865

Ok, I think you missed the most important part. If you want to use Binding you have to set the DataContext somewhere on the view. This is a good start for the theory of Binding.

Usually, you would use a ViewModel for that. E.g.

public class WndViewModel : ViewModelBase // the base class implementing INotifyPropertyChanged
                                          // although you don't need it for your case 
{
    private ObservableCollection<Data> _db;
    public ObservableCollection<Data> Db 
    { 
        get { return _db ?? (_db = new ObservableCollection<Data>()); 
    }

    public WndViewModel()
    {
        Db.Add(new Data { Name = "person1", Description = "sssssss", Price = 15 });
        Db.Add(new Data { Name = "person2", Description = "okokok", Price = 12 });
    }
}

Then you could use the ViewModel like this.

<Window ...>
    <Window.DataContext>
         <someNs:WndViewModel />
    </Window.DataContext>
    <Grid>
        <StackPanel Orientation="Vertical" Name="Panel">
            <TextBlock Name="count"/>
            <DataGrid ItemsSource="{Binding Db}" AutoGenerateColumns="True"/>       
        </StackPanel>
    </Grid>
</Window> 

Please note, that this code is only for demonstration purposes and needs to be improved for a good solution.

I also recommend you to get familar with the MVVM pattern. You may start by reading this article.

Upvotes: 0

Related Questions