1

In my WPF application I have classes Student and StudentDB.

class StudentDB
{
   int StudentId{get;set;}
   string  Name{get;set;}
   string  City{get;set;}
   DateTimeOffset BirthDate{get;set;}
}

class Student
{
   int StudentId{get;set;}
   string  Name{get;set;}
   string  City{get;set;}
   DateTime BirthDate{get;set;}
}

The main difference between two classes is the datatype of the Birthday property. one is DateTime and another one is DateTimeOffset.

Im having following code in my application.

IEnumerable<StudentDB> StudentDbs = GetAllStudentFromDB();
IEnumerable<Student> Students = new IEnumerable<Student> Students();

XAML:

<DataGrid ItemsSource="{Binding Students, Mode=TwoWay}" AutoGenerateColumns="True">

I need to display the list of student in the DataGrid. I cannot bind the StudentDbs since it has a DateTimeOffset type property.

To solve above issue I need to apply a Value Converter, which will convert StudentDb object to Student object.

I know how to implement IValueConverter interface I. But i don't know how to apply it for a collection.

Can anyone suggest me a solution to solve this?

Rahul
  • 2,431
  • 3
  • 35
  • 77
  • 1
    Maybe you can try something similar to [this answer](http://stackoverflow.com/a/7635319/752842) – Dzyann Jan 28 '16 at 13:12

3 Answers3

1

Answer for your primary requirement : DateTimeOffset class has a property called DateTime that represents the date and time of the current System.DateTimeOffset object. So You can still bind StudentDbs as an DataGrid's Itemsource and you can directly bind the BirthDate.DateTime property wherever you want inside the DataGrid to achieve your requirement.

Sivasubramanian
  • 935
  • 7
  • 22
1

You no need a value converter.

The better way is to convert StudentDB to Student via LINQ or in the other way in ViewModel and then bind collection of Student objects to your DataGrid.

IEnumerable<StudentDB> StudentDbs = GetAllStudentFromDB();
IEnumerable<Student> Students = new StudentDbs.Select(student => ConvertToDto(student));

private Student ConvertToDto(StudentDB)
{
    return new Student 
    { 
        StudentId = StudentId, 
        Name = Name, 
        City = City, 
        BirthDate = BirthDate.DateTime 
    };
}

<DataGrid ItemsSource="{Binding Students, Mode=TwoWay}" AutoGenerateColumns="True">

Also it's better to use ObservableCollection<T> to prevent memory leaks and allow collection changes.

Vadim Martynov
  • 8,602
  • 5
  • 31
  • 43
  • @Hi Vadim, Actually I'm using DataServiceCollection (Odata Service) to get list of student from db. So how can i save the changed data (in datagrid) back to database in MVVM way? – Rahul Jan 28 '16 at 15:35
  • @Rahul it depends on many factors for example 1. what ORM do you use. 2. Do you have 2-tiers or 3-tiers app? 3. Do you add/remove items or just change already existed items. Also, it's primary opinion based. Typical I'm using ViewModel-layer, service-layer and data access layer. Service layer contains business logic then it can has StudentsService with UpdateStudents(IEnumeralbe students) method. Business logic will compare DTO with entities and save changes with repository methods. – Vadim Martynov Jan 28 '16 at 19:22
  • I'm using EF and its a 3 tier app. I need to perform crud operations. – Rahul Feb 04 '16 at 17:34
  • Well in 3-tier app you'll have different entities passed to the client and received back. Then you'll need to attach entities manually each time. Yo can read more info [on MSDN](https://msdn.microsoft.com/en-us/data/jj592676.aspx), [SO](http://stackoverflow.com/questions/5550218/attach-collections-in-entity-framework), [CodeProject](http://www.codeproject.com/Articles/576330/Attaching-detached-POCO-to-EF-DbContext-simple-and) and [SO again](http://stackoverflow.com/questions/20451461/save-detached-entity-in-entity-framework-6). – Vadim Martynov Feb 05 '16 at 20:04
0

The value converter musst be applied on the Columns. So set AutoGenerateColumns="False" and add the columns manually:

<DataGrid.Columns>
<DataGridTextColumn Header="{lex:Loc ...}"
Binding="{Binding StarString, Converter={StaticResource ...}}">

When AutoGenerating is true, use the AutoGeneratingColumn Event of the DataGrid. in xaml add:

<DataGrid ItemsSource="{Binding Students, Mode=TwoWay}" AutoGenerateColumns="True" AutoGeneratingColumn="StartListGrid_OnAutoGeneratingColumn"

In the code behind add something like:

private void StartListGrid_OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        if (e.PropertyName == "BirthDate" && e.Column is DataGridTextColumn)
        {
            var textColumn = e.Column as DataGridTextColumn;
            textColumn.Binding = new Binding(e.PropertyName)
            {
                Converter = new MyValueConverter();
            };
        }
    }

Please note that you are overwriting the Binding.

unkreativ
  • 482
  • 2
  • 8
  • I need to generate the columns automatically. Any solution? – Rahul Jan 28 '16 at 15:27
  • The grid raises an event when creating the column. You could use this event to manually generate the binding in code behind. Check this article: https://msdn.microsoft.com/en-us/library/cc903950(v=vs.95).aspx – unkreativ Jan 28 '16 at 15:30
  • Ok, So how do you apply value converter? – Rahul Jan 28 '16 at 16:04