12

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.

user3769902
  • 415
  • 2
  • 5
  • 20
  • What is the problem? Have you read http://stackoverflow.com/questions/15087131/bind-an-observablecollection-to-a-wpf-datagrid-gris-stay-empty? And in which class does your ObservableCollection property located? – Eugene Podskal Jul 02 '14 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. – user3769902 Jul 02 '14 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 – Mr. Blond Apr 11 '15 at 10:36

4 Answers4

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}" />
Nahuel Ianni
  • 3,177
  • 4
  • 23
  • 30
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;
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Rakesh
  • 4,004
  • 2
  • 19
  • 31
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.

Community
  • 1
  • 1
makambi
  • 1,100
  • 3
  • 13
  • 30
  • I don't need to set ObservableCollection itself. I need to set only its items. Thanks. – user3769902 Jul 02 '14 at 19:46
  • 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? – makambi Jul 02 '14 at 21:31
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.