Databinding, using formulas for unusual binding possible?

Posted by Rattenmann on Stack Overflow See other posts from Stack Overflow or by Rattenmann
Published on 2013-11-02T01:27:27Z Indexed on 2013/11/02 3:54 UTC
Read the original article Hit count: 174

Filed under:
|

Edit: added Info for WPF being used

I am trying to bind a list of custom objects to a DataGrid. Straight binding seems easy enough, but i need to specify some complex formulas for some extra fields that do not directly show up in my class. Also i want to be able to EDIT the data in the Grid and get updates on related fields. Let me show you an example, because it is really hard to explain. I will simplify it to rooms with items. Each item can be red and blue.

My Class looks like this:

public class room
{
   public string strRoomName { set; get; }
   public string strItemname { set; get; }
   public int intRedItem { set; get; }
   public int intBlueItem { set; get; }
}

Now if i use dataTable.ItemSource = myList; i get something like this:

nr. | room | name | red | blue

1. living room, ball, 2, 1
2. sleeping room, bunny, 4, 1
3. living room, chair, 3, 2
4. kitchen, ball, 4, 7
5. garage, chair, 1, 4

Now for the complex part i need help with. I want every item to be the same number, red and blue. And because this does not hold true i want to see the "inbalance" per room AND globally like this:

nr. | room | name | red | blue | missing | global red | global blue | global missing 

1. living room, ball, 2, 1, 1 blue, 6, 7, 1 red
2. sleeping room, bunny, 4, 1, 3 blue, 4, 1, 3 blue
3. living room, chair, 3, 2, 1 blue, 4, 6, 2 red 
4. kitchen, ball, 4, 7, 3 red, 6, 7, 1 red
5. garage, chair, 1, 4, 3 red, 4, 6, 2 red

As you can see this smeels like excel formulas, i am unsure how to handle this in c# code however. You can also see i need to use data in the same row, but also get data from other rows that match one propertiy (the items name).

Also if i change the blue value=1 in line 1 to value=2, i want line 1 to read like this:

1. living room, ball, 2, 2, even, 6, 8, 2 red

and of corse line 4 needs to change to:

4. kitchen, ball, 4, 7, 3 red, 6, 8, 2 red

As i said, this smells like excel, that's why i am really upset about myself not finding an easy solution. Surely enough c# offers some way to handle this stuff, right?

Disclaimer: It is totally possible that i need a complete differend approach, pointing that out ot me is perfectly fine. Be it other ways to handle this, or a better way to structure my class. I am ok with every way to handle this as it is for learning purposes. I am simply doing programms for fun next to my college and just so happen to hit these kinda things that bug me out because i don't find a clean solution. And then i neglect my studies because i want to solve my (unreleated to studys,...) issue. Just can't stand having unsolved coding stuff around, don't judge me! ;-)

And big thanks in advance if you have gotten this far in my post. It sure must be confusing with all those reds and blues.

Edit: After reading trough your answers and testing my skills to implement your hints, i now have the following code as my class:

public class RoomList : ObservableCollection<room>
{
    public RoomList() : base()
    {
        Add(new room() { strRoomName = "living room", strItemname = "ball", intRedItem = 2, intBlueItem = 1 });
        Add(new room() { strRoomName = "sleeping room", strItemname = "bunny", intRedItem = 4, intBlueItem = 1 });
        Add(new room() { strRoomName = "living room", strItemname = "chair", intRedItem = 3, intBlueItem = 2 });
        Add(new room() { strRoomName = "kitchen", strItemname = "ball", intRedItem = 4, intBlueItem = 7 });
        Add(new room() { strRoomName = "garage", strItemname = "chair", intRedItem = 1, intBlueItem = 4 });
    }
}
//rooms
public class room : INotifyPropertyChanged
{
    public string strRoomName { set; get; }
    public string strItemname { set; get; }
    public int intRedItem
    {
        get { return intRedItem; }
        set
        {
            intRedItem = value;
            NotifyPropertyChanged("intRedItem", "strMissing");
        }
    }
    public int intBlueItem
    {
        get { return intBlueItem; }
        set
        {
            intBlueItem = value;
            NotifyPropertyChanged("intBlueItem", "strMissing");
        }
    }
    public string strMissing
    {
        get
        {
            int missingCount = intRedItem - intBlueItem;
            return missingCount == 0 ? "Even" : missingCount.ToString();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(params string[] propertyNames)
    {
        if (PropertyChanged != null)
        {
            foreach (string propertyName in propertyNames)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

I got the "missing" field working right away, thanks alot for that tip. It really was as easy as i imagined and will be of great use for future projects.

Still two (three maybe....) things i am missing tho. The above code terminates with a "System.StackOverflowException" in the setter of intRedItem and intBlueItem. I fail to see the error, that could be due to being 4:30am here, or my lack of understanding.

Second issue: I followed the link to ObservableCollections as you can see from my code above. Yet i am unsure how to actually use that collection. Putting it as DataContent like suggested on that page shows a missing ressource. Adding it as a ressource like listed there crashes my VSExpress designer and leads to the programm not starting. So for now i am still using my old approach of a list like this:

            listRooms.Add(new room() { strRoomName = "living room", strItemname = "ball", intRedItem = 2, intBlueItem = 1 });
        listRooms.Add(new room() { strRoomName = "sleeping room", strItemname = "bunny", intRedItem = 4, intBlueItem = 1 });
        listRooms.Add(new room() { strRoomName = "living room", strItemname = "chair", intRedItem = 3, intBlueItem = 2 });
        listRooms.Add(new room() { strRoomName = "kitchen", strItemname = "ball", intRedItem = 4, intBlueItem = 7 });
        listRooms.Add(new room() { strRoomName = "garage", strItemname = "chair", intRedItem = 1, intBlueItem = 4 });
        datagridRooms.ItemsSource = listRooms;

And lastly: When testing before adding the notifyevents i tried to implement a proterty that looped trough the other objects, without any luck. The "missingItem" property worked so easy, yet it only tries to access "it's own" properties kind of. I need to access other objects, like "all objects that have the same room value". The idea behind this is that i am trying to calculate a value from other objects without even having those objects yet, at least in my logic. Where is the flaw in my thinking?

Those 5 objects are added and created (?) one after another. So if the first tries to set it's "all red balls in my room AND all other rooms" value,.. how could it know about the balls in the kitchen, that get added as 4th object?

So far so good tho, got on the right track i think. Just need some sleep first.

© Stack Overflow or respective owner

Related posts about c#

Related posts about wpf