Click here to Skip to main content
15,881,967 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,
I'm a beginner in programming, C#, WPF, everything really and I'm learning by creating an application where you can draw out a drainage network, and carry out a bunch of calculations on that network.
I'm using WPF and drawing lines and nodes on a canvas.

My initial plan was, when a node is placed on the canvas, an entry into an SQLite database is created as a convenient way to store the data, query it, and modify it at a later stage.
It's also convenient that the database can be saved and loaded making the whole file open/save element really straight forward.
I plan to also use the data in the database to redraw to the canvas in the event of a pan of zoom (not built in yet).

The problem is I also have to create an instance of the class "Node" in order to place it on the Canvas.

This would be ok, until the user wants to edit the network, which is the next bit I want to work on.

It's easy enough to find the node in the database when the user clicks in the vicinity of the node.
But then how would also also modify the class for that node shown on screen?
I could clear the canvas and redraw everything form the database but that seems very inefficient.

I assume I could create a list of all the instances of the node class, and then use LinQ to find that node instance, and modify it, but then I'm having to do the query twice which again doesn't seem very efficient.
I'm also unclear how I would access that class since they all effectively have the same name `node`.

So my questions are:
1. Should I avoid using the database and rely solely on the node class to query, modify etc?
2. Regardless of the answer to question 1, how do I modify a specific instance of "node"?

Many thanks.

What I have tried:

Here is my method to create a new node:

private void AddNode(MouseButtonEventArgs e)
        {
            Node node = new Node();
            CadCanvas.Children.Add(node.DrawNode(currentMousePoint.X, currentMousePoint.Y));
            
            database.AddNode("test", currentMousePoint.X, currentMousePoint.Y);

        }




and here is my node class that creates the graphic for the canvas:

public class Node
    {

        public int id;
        public string refernce;


        public Ellipse DrawNode(double x, double y)
        {
            Ellipse e = new Ellipse();
            e.Height = 20;
            e.Width = 20;
            e.Fill = Brushes.Blue;

            double left = x - (20 / 2);
            double top = y - (20 / 2);

            e.Margin = new Thickness(left, top, 0, 0);

            return e;

        }

    }
Posted
Updated 19-Apr-21 23:44pm
Comments
Richard MacCutchan 16-Apr-21 9:17am    
            double left = x - (20 / 2);
            double top = y - (20 / 2);

20 divided by 2 will always result in 10. I suspect that is not the calculation you really want.
Richard!i! 16-Apr-21 10:05am    
Hi, it is for now.
The 20 will eventually be replaced by a variable to allow the user to select different node sizes and keep the positioning in the center of the node.
Whilst I'm experimenting I find it easier to hard code such things and sort it later.
If I write 10, it might be that little bit harder for me to remember what it is in the future.
Richard MacCutchan 16-Apr-21 10:38am    
OK.

As to your questions, I would just say that assuming the number of nodes is not such that they fill your memory it makes sense to read them in to a List<t> first. That saves you lots of database accesses; you only need it to write updated nodes.
Richard!i! 16-Apr-21 12:15pm    
Thanks for that.
I hadn't released you could place instances of a class in a list. So in my case:
List<node> nodeList = new List<node>();
I'll have a play this weekend and see how I get on. If it works as I expect it will basically be like a database which is great.
Follow up question if I may, if I know I'm only going to need one copy of this list for the whole application and I will want to modify it and read it form multiple classes, would it be so terrible if I placed it in a static class to save creating multiple instances and referencing them all together and passing them around.
Richard MacCutchan 16-Apr-21 12:26pm    
Instances of a class are just objects, and are not so different from fundamental types (int, char etc.), in how they may be manipulated.

You do not need to put it in a static class, and you do not need to create multiple instances, of the List. If you feel that need then something is wrong with your design.

1 solution

The proper way to approach this is with the MVVM (Model-View-ViewModel) pattern.

The model is responsible for loading and saving the data.

The viewmodel is an instance of the model that contains additional code to allow viewing/manipulation in the view.

The view uses (binds to) the viewmodel, and doesn't know anything about the model, or where the data might come from.

Honestly, the topic of MVVM is way too huge to cover in a QA answer, and you'd be much better served by searching CodeProject for articles relating to it.

My advice is to nail down the model/viewmodel interaction, and THEN worry about presenting the viewmodel in the UI. I've written a number of articles here that use MVVM in a WPF ecosystem. Those articles contain code to make your WPF MVVM live a lot simpler.
 
Share this answer
 
v2
Comments
Richard!i! 20-Apr-21 8:21am    
Hello, thanks for your advice. I went down a bit of a reading rabbit hole this weekend and thankfully came up with a similar conclusion.
I mostly read about MVVM, SOLID and took a particular interest in the Dependency inversion, that if implemented through Dependency Injection would allow me to inject either new instances everytime I have a class that needs one, or apparently I can inject an object (I think the term was singleton) which would mean that all my viewmodels can access and modify that one instance which would help my hugely.
I've started having a little play with mvvmCross library which should handle all of the above to allow me to get going a little quicker.
Thanks again

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900