0

I'm using a DataGrid to get input from the user and place it in a List. I've used the DataGrid.ItemSource property to bind the DataGrid to a List I've created. During runtime however, when I edit the DataGrid the List that is bound to it is not updated automatically.

I start by defining a List (loadTable) of a custom type (PedLoad):

//Defines pedestal loads for a footing
struct PedLoad
{
    public string LoadCase { get; set; }    //Load case description
    public double Axial { get; set; }       //Axial force (tension or compression)
    public double Shear { get; set; }       //Shear force
    public double Moment { get; set; }      //Moment
}

//Create the load list
List<PedLoad> loadTable = new List<PedLoad>();

Later on in the code I add items (PedLoads) to the List (loadTable) and bind it to the DataGrid (dgdLoadTable) as follows:

//Bind the datagrid to the load table
dgdLoadTable.ItemsSource = loadTable;

//Populate the load case names
DL.LoadCase = "Dead (D)";
LL.LoadCase = "Live (L)";
LLR.LoadCase = "Roof Live (Lr)";
SL.LoadCase = "Snow (S)";
WL.LoadCase = "Wind (W)";
EL.LoadCase = "Seismic (E)";

//Add the loads to the load list/datagrid
loadTable.Add(DL);
loadTable.Add(LL);
loadTable.Add(LLR);
loadTable.Add(SL);
loadTable.Add(WL);
loadTable.Add(EL);

This works just fine, except when I update the DataGrid, the List (loadTable) does not keep up with it. How can I get the List to update whenever the DataGrid is edited by the user?

Here's the full code, modified with an ObservableCollection:

public partial class MainWindow : Window { //Create the sketch objects Rectangle slab = new Rectangle(); Rectangle pedestal = new Rectangle();

    //Create the load table and the results table
    ObservableCollection<PedLoad> loadTable = new ObservableCollection<PedLoad>();
    ObservableCollection<ServiceResults> resultsTable = new ObservableCollection<ServiceResults>();

    public MainWindow()
    {
        InitializeComponent();

        //Bind the datagrids to the load tables

        dgdResultsTable.ItemsSource = resultsTable;

        //Populate the load case names
        loadTable.Add(new PedLoad { LoadCase = "Dead (D)" });
        loadTable.Add(new PedLoad { LoadCase = "Live (L)" });
        loadTable.Add(new PedLoad { LoadCase = "Roof Live (Lr)" });
        loadTable.Add(new PedLoad { LoadCase = "Snow (S)" });
        loadTable.Add(new PedLoad { LoadCase = "Wind (W)" });
        loadTable.Add(new PedLoad { LoadCase = "Seismic (E)" });

        dgdLoadTable.ItemsSource = loadTable;

        //Analyze the footing
        Analyze();

        //Adjust the color of the sketch objects
        slab.Fill = Brushes.LightSlateGray;
        pedestal.Fill = Brushes.LightSlateGray;

        //Add the sketch objects to the canvas
        cvsSketchArea.Children.Add(slab);
        cvsSketchArea.Children.Add(pedestal);

        //Update the sketch
        UpdateSketch();
    }

    //Analyzes the footing
    private void Analyze()
    {
        //Clear out old results
        resultsTable.Clear();

        //Create a list of service footings
        List<SpreadFooting> serviceFtgs = new List<SpreadFooting>();

        //Populate the list with the basic footing data
        for (int i = 0; i < 13; i++)
        {
            SpreadFooting newFtg = new SpreadFooting();
            newFtg.L = double.Parse(txtFtgLength.Text);
            newFtg.B = double.Parse(txtFtgWidth.Text);
            newFtg.h = double.Parse(txtFtgThickness.Text) / 12;
            newFtg.hp = double.Parse(txtPedHeight.Text);
            newFtg.wp1 = double.Parse(txtPedWidth1.Text) / 12;
            newFtg.wp2 = double.Parse(txtPedWidth2.Text) / 12;
            newFtg.ep = double.Parse(txtPedEcc.Text);
            newFtg.wc = double.Parse(txtConcreteWt.Text) / 1000;
            newFtg.wo = double.Parse(txtOverburden.Text) / 1000;
            serviceFtgs.Add(newFtg);
        }

        //Populate the list with the load data
        //D
        serviceFtgs[0].Description = "D";
        serviceFtgs[0].P = loadTable[0].Axial;
        serviceFtgs[0].V = loadTable[0].Shear;
        serviceFtgs[0].M = loadTable[0].Moment;

        //D+L
        serviceFtgs[1].Description = "D+L";
        serviceFtgs[1].P = loadTable[0].Axial + loadTable[1].Axial;
        serviceFtgs[1].V = loadTable[0].Shear + loadTable[1].Shear;
        serviceFtgs[1].M = loadTable[0].Moment + loadTable[1].Moment;

        //D+Lr
        serviceFtgs[2].Description = "D+Lr";
        serviceFtgs[2].P = loadTable[0].Axial + loadTable[2].Axial;
        serviceFtgs[2].V = loadTable[0].Shear + loadTable[2].Shear;
        serviceFtgs[2].M = loadTable[0].Moment + loadTable[2].Moment;

        //D+S
        serviceFtgs[3].Description = "D+S";
        serviceFtgs[3].P = loadTable[0].Axial + loadTable[3].Axial;
        serviceFtgs[3].V = loadTable[0].Shear + loadTable[3].Shear;
        serviceFtgs[3].M = loadTable[0].Moment + loadTable[3].Moment;

        //D+0.75(L+Lr)
        serviceFtgs[4].Description = "D+0.75(L+Lr)";
        serviceFtgs[4].P = loadTable[0].Axial + 0.75 * (loadTable[1].Axial + loadTable[2].Axial);
        serviceFtgs[4].V = loadTable[0].Shear + 0.75 * (loadTable[1].Shear + loadTable[2].Shear);
        serviceFtgs[4].M = loadTable[0].Moment + 0.75 * (loadTable[1].Moment + loadTable[2].Moment);

        //D+0.75(L+S)
        serviceFtgs[4].Description = "D+0.75(L+S)";
        serviceFtgs[4].P = loadTable[0].Axial + 0.75 * (loadTable[1].Axial + loadTable[3].Axial);
        serviceFtgs[4].V = loadTable[0].Shear + 0.75 * (loadTable[1].Shear + loadTable[3].Shear);
        serviceFtgs[4].M = loadTable[0].Moment + 0.75 * (loadTable[1].Moment + loadTable[3].Moment);

        //Populate the results table
        for (int i = 0; i < 13; i++)
        {
            serviceFtgs[i].Calculate();
            resultsTable.Add(serviceFtgs[i].Results1);
        }

    }
DCB2524
  • 31
  • 1
  • 8

1 Answers1

1

Use ObservableCollection instead of List :

    private void dgdLoadTable_Loaded(object sender, RoutedEventArgs e)
    {
        loadTable = new ObservableCollection<PedLoad>();

        loadTable.Add(new PedLoad { LoadCase = "Dead (D)" });
        loadTable.Add(new PedLoad { LoadCase = "Live (L)" });
        loadTable.Add(new PedLoad { LoadCase = "Roof Live (Lr)" });
        loadTable.Add(new PedLoad { LoadCase = "Snow (S)" });
        loadTable.Add(new PedLoad { LoadCase = "Wind (W)" });
        loadTable.Add(new PedLoad { LoadCase = "Seismic (E)" });

        dgdLoadTable.ItemsSource = loadTable;
    }
    private void Button1_Click(object sender, RoutedEventArgs e)
    {
        loadTable.Add(new PedLoad { LoadCase = "New Item" });
    }

Result:

enter image description here

The ObservableCollection is definitely updated after user editing : enter image description here

jsanalytics
  • 13,058
  • 4
  • 22
  • 43
  • I just changed it to an ObservableCollection and it still does not update the ObservableCollection when the DataGrid is updated. In the code above, what is the value of loadTable[4].Description once you've changed the DataGrid? Did it update automatically? – DCB2524 Aug 02 '15 at 02:42
  • ObservableCollection does it all for you. Make sure loadTable in your code is a class instance variable and not a local variable within some method. Are you sure of that? – jsanalytics Aug 02 '15 at 02:47
  • Try placing a breaking point in your debugger to see values you want, like loadTable[4].Description. – jsanalytics Aug 02 '15 at 02:54
  • How do you know that DataGrid is updated but ObservableCollection is not? – jsanalytics Aug 02 '15 at 02:56
  • I added a debugger picture showing the updated collection after user editing, just in case you're still not sure...:) – jsanalytics Aug 02 '15 at 03:04
  • I must be doing something wrong. I've added my full code for the window. – DCB2524 Aug 02 '15 at 04:00
  • I see you're creating an instance of loadTable within the class but outside any methods. I would create an instance either during the "Window_Loaded" event or within MainWindow() constructor. – jsanalytics Aug 02 '15 at 06:34
  • Also you're adding data and assigning it to ItemsSource inside the constructor. I would move the whole thing to the Window_Loaded event. Take another look how I did it in my code. – jsanalytics Aug 02 '15 at 06:41
  • Still no luck. Do you think it's a problem with a property in my datagrid? – DCB2524 Aug 03 '15 at 20:26
  • No, I don't think so... strange thing is that my latest post to your question is not showing up in this page... Right now I'm installing VS 2015 but once it is finished I'm going to copy your full code and look at it. – jsanalytics Aug 03 '15 at 21:40
  • Oh no... I'm confusing your question with another similar question I answered. I think you should start fresh from a simple code base like the one I posted, get the a DataGrid working first and then work backwards from there adding your actual code bit by bit and see where it breaks. – jsanalytics Aug 03 '15 at 22:03
  • Can you get any simple datagrid working at all? Do that first and then grow your code base from there. – jsanalytics Aug 03 '15 at 22:04