0
votes

I need help with binding. Its WPF MVVM pattern. I have placed a datagrid and three ICommand buttons 'Add', 'Modify', 'Delete' buttons, in a UserControl (UC). The add, modify, delete buttons are to facilitate operations to the datagrid. Calling this UC 5 times in a XAML window (Main window). The button controls are handled in the view model of the main XAML window. For instance, AddStudent for Add button, ModifyStudent for Modify button and DeleteStudent for Delete button. But there is only one handler for all the 5 instance of the UC. For instance, click on the Add button from any of the 5 instances of the UC, it calls the same AddStudent function.

But the problem is, the 5 UC instance has to bind to 5 different Students class, Engineering, Medical, Architecture and so on.

here is Student entity containing student details.

So when I click on the Medical Student datagrid's Add button, a dialog would popup asking for student details that should be inturn added to the Medical Student's datagrid. Same goes to other 4 datagrids. All these should be done in view model. But the problem is, since all the 5 instances call the same AddStudent method, the new student added is reflecting in all 5 datagrids. I want to be able to bind the respective Student list to its corresponding datagrid control. Need help with the binding. PS: I have made the ITemsSource of the UC a Dependency Property.

Student is not an interface. Its an entity class.

public class College 
{ 
    private string code; 
    private string name; 

    private Student engineering; 
    private Student medical;
    private Student nursing; 
    private Student architecture; 
    private Student fashionDesign; 

     public Student Engineering 
     { 
         get 
         { 
             return engineering;
         } 
         set 
         { 
            SetField(ref engineering, value, () => Engineering); 
         } 
     } 
 } 

Where Student is a class. Unfortunately, I dont have the liberty to change it to an Interface. Any other way to bind each of these to its corresponding datagrid.

1
If student is an Interface implemented by the various classes then just test the item for the class. if (item is Engineering) ... - paparazzo
Blam, Thanks for the initial response. Student is not an interface. Its an entity class. public class College { private string code; private string name; private Student engineering; private Student medical; private Student nursing; private Student architecture; private Student fashionDesign; public Student Engineering { get { return engineering;} set { SetField(ref engineering, value, () => Engineering); } } } Where Student is a class. Unfortunately, I dont have the liberty to change it to an Interface. Any other way to bind each of these to its corresponding datagrid. - TechBang
You really expect me to read that comment. Put code in a code block in the question. - paparazzo
Oops sorry!, I dont see a code block enabled for me. All I see is 'Add Comment' button. - TechBang
You don't see in edit? IN the question. Look at other questions. - paparazzo

1 Answers

0
votes

How you have written that college class makes it look like each college can only have 1 of each type of student? surely a college would have a whole list of students, and what if you're asked to add more courses? you're going to end up with grids everywhere and a big mess.

My suggestion would be to add a StudentType (as an enum) onto your student class.

So my enum:

public enum TypeOfStudent
{
    Engineering,
    Medical,
    Computing,
    Fashion     
}

Add it as a property to your student class:

public class Student
{
    public TypeOfStudent StudentType;

    //and other details as required...
}

Then you just need a list of students in your College class and only one set of buttons on your form. For the add student method to know what type of student you want to add, then on your form where your asking for students info add a simple combobox containing your enum values for the user to select from would work.

public class College
{
    //property that contains ALL of the students
    public ObservableCollection<Student> Students

    //property containing the a filtered list of students. Your grid will bind its itemssource to
    //this property. You will need to set this property to equal students on initial load up so
    //it will display all students
    public IEnumerable<Student> FilteredStudents { get { return _filteredStudents; } }

    //property that returns the values in your enum which you can bind a combobox's itemsource to
    public IEnumerable<TypeOfStudent> StudentTypes
    {
        get { return Enum.GetValues(typeof(TypeOfStudent)).Cast<TypeOfStudent>(); }
    }

    //property that stores the selected student type which should be bound to a combobox's
    //selecteditem.
    public TypeOfStudent SelectedStudentType {  get; set + Raise PropertyChanged stuff;  }

    //property storing the selected filter for type of student
    public TypeOfStudent SelectedFilter {get; set + raise propertychanged; }

    //method for adding a student to your list of students
    public void AddStudent()
    {
        this.Students.Add(new Student
        {
            StudentType = this.SelectedStudentType
        });
    }

    //method of applying a filter
    public void FilterStudents()
    {
        _filteredStudents = this.Students.Where(s=>s.StudentType == this.SelectedFilter);
    }
}

As for getting your one datagrid to show students of a specific type. If you give the user a combobox with a list of student types, then when they select something you can use the filter students method to update the grid.

Now there are a few things i've left out. For example you would probably want some kind of 'All' option in the filter. And you'll need to do some raise property changed events on the lists etc. but what i've written should make the whole thing more manageable.