views:

132

answers:

5

In my C# winforms application I need to draw blocks. These blocks are so called process blocks. All the blocks together are a process. There are different kinds of process blocks. At this moment I have three kinds of process blocks: A, B, C. When I draw a process block it looks like this:

A

B

B

C

A

Every block has it's own backgroundcolor. And every block has it's own properties. For example: process block A and B both has the same properties (ID and description). The difference is the background color of the block.

I already have created a user control. This user control is a process block. I already have a picturebox where I add the user control (process blocks) to the controls collection. This works fine. The point is that I don't know how to link a process block of type A, B, C to the user control. I also have a propertygrid. When a processblock is clicked I want to display it's property values.

I don't know exactly how to implement this. I hope you can point me at the right direction.

A: 

Add a property to the control to reference the process.

When clicked, link the Process object to the property grid, not the control itself.

(Is this some kind of homework?)

GvS
No this is for my work. I'm a junior programmer and not familiar with this kind of projects.
Martijn
+3  A: 

I would see the UserControl that you've created as a 'visualizer' of a ProcessBlock instance.

So, what I would do -given the information you've given-, is create an abstract class (or interface, it depends) 'ProcessBlock', which has some abstract methods like GetDrawingColor.

For every concrete ProcessBlock, you create a new class which inherits from the abstract class (or interface). So, then you could have 'ProcessBlockA', 'ProcessBlockB', and 'ProcessBlockC' which inherit from the ProcessBlock base class. In each concrete subclass, you override the the GetDrawingColor method, so that it returns the Color that you want to have.

Then , you pass an instance of a ProcessBlock to the UserControl, and the UserControls calls the GetDrawingColor method, and it uses the result in order to paint it's background.

For instance:

public abstract class ProcessBlock
{
    public abstract Color GetDrawingColor();
}

public class ProcessBlockA : ProcessBlock
{
    public override Color GetDrawingColor() 
    { 
       return Color.Blue; 
    }
}

public class ProcessBockB : ProcessBlock
{
    public override Color GetDrawingColor() 
    { 
       return Color.Red;
    }

}

public ProcessBlockVisualizer : UserControl
{
    private ProcessBlock _pb;

    public ProcessBlockVisualizer( ProcessBlock pb )
    { 
         _pb = pb;
         this.BackgroundColor = _pb.GetDrawingColor();

         this.Enter += (object sender, EventArgs e)=> this.PropertyGrid.Datasource = _pb;

    }           
}
Frederik Gheysels
Thanks. I think this gets me started
Martijn
Instead of abstract classes i would prefer interfaces, cause there is no base functionality which should be in every class
Oliver
Oliver: That's why i've said 'abstract class or interface, depending on the situation'. If there is no common functionality for all processblocks, i would indeed prefer an interface as well.
Frederik Gheysels
+1  A: 

Define a ProcessBlock abstract type that defines the properties of a process block, and then derive ProcessBlockA, B and C from ProcessBlock as concrete types. Now you can add a ProcessBlock property to your user control and assign instances of the process types to each.

To allow editing of the process type in a property grid you just assign the user controls ProcessBlock to the property grids SelectedObject property.

Rune Grimstad
So if I have three different process blocks I have to create three abstract classes?
Martijn
No, one abstract class 'ProcessBlock'. If you have 3 different process blocks, you create 3 'concrete' classes that inherit from the abstract class (like i've shown in my answer)
Frederik Gheysels
@Frederik: I understand your answer. Does Rune mean the same as you?
Martijn
Yep. One abstract base class that serves as the common definition of your process blocks. Then you add three concrete classes that define how each type of process block should look.
Rune Grimstad
A: 

You could build a class of "process blocks" something like:

public class processBlock
{
  public int processID(){get; set;}
  public Color processColor(){get; set;}
  public string processName(){get; set;}
  ...other properties...
}

and

public List<processBlock> blockList = new List<processBlock>(new processBlock(processID = 1...));

and add a property to the control that will reference a certain instance of this class.

And build a onClick method that will get the instance from the list and all it's properties.

GxG
when you make a new instance of the class you can set those properties(if all blocks have the same properties but property values differ) if properties differ from one process block to another then you could build a class that has 2 members 1. PropertyName and 2. PropertyValuethen build a class for processes where you use the first class to declare properties thus when you instantiate a new process block it will have different properties
GxG
I don't understand it completely. can you give a small example?
Martijn
+1  A: 
    public class ProcessProperties
{
    public string PropertyName(){get; set;}
    public string PropertyValue(){get; set;}
}



public class ProcessBlock
{
    private List<ProcessProperties> _propList;
    public List<ProcessProperties> propList(){get{return _propList;} set{this.Add(value);}}
}

ProcessBlock A = new ProcessBlock();
ProcessProperties pp = new ProcessProperties();
pp.PropertyName = "something";
pp.PropertyValue = "value of something";
A.propList = pp;

ProcessBlock B = new ProcessBlock();
ProcessProperties ppB = new ProcessProperties();
ppB.PropertyName = "something else";
ppB.PropertyValue = "value of something else";
B.propList = ppB;

Something like this. I don't know if it'll work exactly like what i wrote. usually putting a setter on a property of type List is not correct, but it might work. if it doesn't then instatiate the List some other way(using a constructor for example).

public class ProcessBlock
    {
        private List<ProcessProperties> _propList;
        public List<ProcessProperties> propList(){get{return _propList;}}
        public ProcessBlock(List<ProcessProperties> properties)
        { _propList = properties; }
    }
GxG
Thanks I get it now. I'm still puzzling with the implementation, I will consider this approach.
Martijn
the implementation is simple List<ProcessProperties> pp = new ...; pp.add(new ProcessProperties(){PropertyName = ""; PropertyValue = "";}); pp.add(....); ProcessBlock A = new ProcessBlock(pp);Good Luck
GxG