14

Can you give me a tip how to bind a WPF DataGrid to ObservableCollection. I had seen some posts and didn't find a direct answer. There and everywhere intricate problems are described but my problem rather is not sophisticated. I have an observable collection and WPF DataGrid. Both of them are in WPF application which is a client of a duplex contract WCF service. Here is an ObservableCollection:

private ObservableCollection<MyClass> _myCollection = new ObservableCollection<MyClass>();
public ObservableCollection<MyClass> DownloadsCollection
{
    get { return this._downloadsCollection; }
}

Here is a XAML markup with DataGrid:

<Window x:Class="DownloadManager_Client.MainWindow"
. . . . . . . .>

    <DataGrid Name="dgDownloadsInfo" Grid.Row="2" Grid.Column="0" AutoGenerateColumns="False" CanUserAddRows="False"
              CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="False"
              CanUserResizeRows="False" CanUserSortColumns="False" SelectionMode="Single" SelectionChanged="dgDownloadsInfo_SelectionChanged">
          <DataGrid.Columns>
                <DataGridTextColumn Header="DownloadId" Visibility="Hidden"/>
                <DataGridTextColumn Header="Target URL" FontFamily="Arial" />
                <DataGridTextColumn Header="Content Size" FontFamily="Arial"/>
                <DataGridTextColumn Header="Path to Save" FontFamily="Arial"/>
                <DataGridTextColumn Header="Bytes Downloaded" FontFamily="Arial"/>
                <DataGridTextColumn Header="Percent (%)" FontFamily="Arial"/>
                <DataGridTextColumn Header="Status" FontFamily="Arial"/>
          </DataGrid.Columns>
    </DataGrid>
. . . . . . . .
</Window>

And here is myClass class. It implemented in WCF service. Client receives instances of MyClass in callbacks from WCF service with duplex contract. After each instance of MyClass has been received then it is put in the ObservableCollection to substitute previous one with the same unique identifier.

[DataContract]
public class MyClass
{
    #region Properties

    /// <summary>
    /// Downloading unique ID.
    /// </summary>
    [DataMember]
    public Guid UniqueId { get; set; }
    /// <summary>
    /// Target URL.
    /// </summary>
    [DataMember]
    public String TargetUrl { get; set; }
    /// <summary>
    /// Path to Save.
    /// </summary>
    [DataMember]
    public String PathToSave { get; set; }
    /// <summary>
    /// Percentage.
    /// </summary>
    [DataMember]
    public Int32 Percentage { get; set; }
    /// <summary>
    /// Downloaded bytes number.
    /// </summary>
    [DataMember]
    public Int64 DownloadedBytesQuantity { get; set; }
    /// <summary>
    /// Content size.
    /// </summary>
    [DataMember]
    public Int64 RealContentLength { get; set; }
    /// <summary>
    /// Downloading status.
    /// </summary>
    [DataMember]
    public String Status { get; set; }

    #endregion
}

How can I bind DataGrid to ObservableCollection in my example? Give a hint on this topic. I bag your pardon for my poor English.

3
  • What is the problem? Have you read stackoverflow.com/questions/15087131/…? And in which class does your ObservableCollection property located? Commented Jul 2, 2014 at 19:08
  • 1
    ObservableCollection is located in the class of Main Window of WPF application which is the client of WCF service and so is the DataGrid. Commented Jul 2, 2014 at 19:13
  • 1
    I have the same issue.. For some reason the data contract class is not working with observablecollection. I changed to simple class and it worked... @user3769902 Commented Apr 11, 2015 at 10:36

4 Answers 4

11

You should be able to do so by using the ItemsSource property of the grid and referencing your collection (probably located in your view model), like this:

ItemsSource="{Binding Path=DownloadsCollection}" 

Then add a binding on your columns to show the info (properties) of your MyClass objects in the collection.

For a more detailed tutorial on how to do it, check this link.

Edit:

You can simply try something like this to see if everything works right and then move to custom columns:

<DataGrid ItemsSource="{Binding DownloadsCollection}" />
Sign up to request clarification or add additional context in comments.

4 Comments

<DataGrid ItemSource="{Binding Path=DownloadsCollection}" . . . > </DataGrid> this way?
Yes, but don't forget to bind the values on the columns. Either that or make the grid auto generate columns (another one of its properties), and delete your own declaration for them.
Please write how to bind the values on the columns. No, no I'm clear in it. Thanks.
It should like like this: <DataGridTextColumn Header="DownloadId" Visibility="Hidden" Binding="{Binding TargetUrl}"/> Check the link I have on the post, it explains everything you need to know.
5
<DataGrid x:Name="employeeGrid" HorizontalAlignment="Center" VerticalAlignment="Center" AlternatingRowBackground="LightBlue" AlternationCount="2" AutoGenerateColumns="False" ItemsSource="{Binding}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Emp #" Binding="{Binding EmpId}"/>
        <DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"/>
        <DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
    </DataGrid.Columns>
</DataGrid>

Following goes in your corresponding .cs file:

employeeGrid.ItemsSource = employeeDetails;

Comments

1

Datagrid binding in WPF check this answer. Basically you need to add ItemSource binding so your grid knows the datacontext.

Than you need to add binding for datagrid columns, so it knows what to display. Hope this helped.

Furthermore, you may want to add setter for your DownloadsCollection and binding mode if necessary. It is helpful if you need some updates.

2 Comments

I don't need to set ObservableCollection itself. I need to set only its items. Thanks.
Sorry, I dont get it) You need to set DownloadsCollection as datacontext. DataGrid itself is smart enough to iterate though datacontext and use binding to display items. Is it what you need?
0

You can have your dynamic data grid fill like this:

ObservableCollection<CaseItem> data = new ObservableCollection<CaseItem>();
this.CasesDataGrid.ItemsSource = data;

But don't forget to bind the columns with the each item of your class.

XAML code would be something like this:

<DataGrid x:Name="CasesDataGrid" Grid.Row="1" Grid.Column="0" AutoGenerateColumns="False" SelectionUnit="FullRow" SelectionMode="Extended" CanUserAddRows="False" GridLinesVisibility="Horizontal">
<DataGrid.Columns>
<DataGridTextColumn Width="*" Header="ID" Binding="{Binding CaseID}"/>
<DataGridTextColumn Width="*" Header="Date" Binding="{Binding CaseDate}"/>
<DataGridTextColumn Width="*" Header="Plate" Binding="{Binding CasePlate}"/>
<DataGridTextColumn Width="*" Header="Candidate" Binding="{Binding CaseCandidate}"/>
<DataGridTextColumn Width="*" Header="Base" Binding="{Binding CaseBase}"/>
<DataGridTextColumn Width="*" Header="Speed" Binding="{Binding CaseSpeed}"/>
<DataGridTextColumn Width="*" Header="Photo" Binding="{Binding CasePhoto}"/>
</DataGrid.Columns>
</DataGrid>

Hope it's useful to you.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.