0
votes

We use C# form applications as HMI for our Automation projects. While doing this we generally use button click events. These events are changed boolean values from false to true. My problem starts here. There are lots of boolean and if I add button events one by one, I will spend many many times. So I want to do my own button component and. I will drag and drop my button from toolbox and relate it with a boolean using properties window. After doing this, It will do everything automaticly instead of me. Button design is not important for me.

Example:

//Define Variables
public class PLCVars
{
    public bool PLCVar1;
    public bool PLCVar2;
    public bool PLCVar3;
    public bool PLCVar4;
    public bool PLCVar5;
    public bool PLCVar6;
    public bool PLCVar7;
    public bool PLCVar8;
}

//(!)I have a PLCVars object defined as PLCVariables
//Button Events 
private void button_JogPLCVar1_MouseDown(object sender, MouseEventArgs e)
{
    PLCVariables.PLCVar1 = true;
}

private void button_JogPLCVar1_MouseUp(object sender, MouseEventArgs e
{
    PLCVariables.PLCVar1 = false;
}

As shown above example, I want to relate my button component with a plc variable. It will make all mouseup and mousedown events automaticly and change the value of plc variables.

As I searched, I should use Custom Control. But I don't know relating form variables with Custom Control components is posibble. If it is possible how?

3
Can you please clarify some parts of your question. There are lots of boolean and if I add button events one by one - What boolean? Is it like bool x = false;? How you add events to boolean? Show us this code. relate it with a boolean using properties window - what does it mean? How you relate button with boolean? - Sergey Berezovskiy
I edited my question with adding code parts. - tebdilikiyafet

3 Answers

1
votes

You can do this simply by putting a Panel into the Form and create Button control's dynamically and also attach events to the created controls.

Here is a row example (you have to modify it)

public class PLCVars
{
    public bool PLCVar1;
    public bool PLCVar2;
    public bool PLCVar3;
    public bool PLCVar4;
    public bool PLCVar5;
    public bool PLCVar6;
    public bool PLCVar7;
    public bool PLCVar8;

    public bool[] BooleanVars()
    {
        return new bool[] { PLCVar1, PLCVar2, PLCVar3, PLCVar4, PLCVar5 };
    }
}

public void Method()
{
     PLCVars v = new PLCVars();

     panel1.Controls.Clear();

     for (int i = 1; i < 5; i++)
     {
         Button button = new Button();
         button.Name = "Button" + i;
         button.MouseUp += delegate 
         {
             v.BooleanVars()[i] = false;
         };
         button.MouseDown += delegate
         {
             v.BooleanVars()[i] = true;
         };

         panel1.Controls.Add(button);
     }
}
1
votes

After your update I see that you want to create some buttons and manage properties of some object with these buttons. Here is much better solution.

First - you should use FlowLayoutPanel to host your buttons. Buttons will be located dynamically.

Second - you should not use buttons. Use CheckBoxes with button's appearance. Because you need to manage boolean properties.

Thirs - you should change PLCVars fields into properties. Because we are going to use data binding. And it doesn't work with fields:

public class PLCVars
{
    public bool PLCVar1 { get; set; }
    public bool PLCVar2 { get; set; }
    public bool PLCVar3 { get; set; }
    public bool PLCVar4 { get; set; }
    public bool PLCVar5 { get; set; }
    public bool PLCVar6 { get; set; }
    public bool PLCVar7 { get; set; }
    public bool PLCVar8 { get; set; }
}

Now you don't need any event handlers or custom buttons. If you want to create UI to control properties of PLCVariables object you just need to add checkboxes to panel and bind them to your object. Easy:

int numberOfVlcVariables = typeof(PLCVars).GetProperties()
      .Count(p => p.Name.StartsWith("PLCVar"));

for(int i = 1; i <= numberOfVlcVariables ; i++)
{
    CheckBox cb = new CheckBox();
    cb.Appearance = Appearance.Button;
    cb.Text = "PLCVar" + i;
    cb.DataBindings.Add("Checked", PLCVariables, "PLCVar" + i);
    flowLayoutPanel1.Controls.Add(cb);
}

That creates and arranges toggle 'buttons'. And each button controls appropriate property of PLCVariables object. I.e. when button is pressed down, it means property set to true. If button is up, then property is equal to false.

enter image description here

And even more simple, but less cool option - you can simply add PropertyGrid control to your form and assign PLCVariables object to it:

propertyGrid1.SelectedObject = PLCVariables;

Result:

enter image description here

0
votes

There is no need for custom control. Subscribe all buttons to these two event handlers. All you need to do is get PLCVar# field name. And you can use button's Tag property for that. Assign field name to tags PLCVar1, PLCVar2 etc. Then get field name in event handler and assign value via reflection:

private void button_JogPLCVar_MouseDown(object sender, MouseEventArgs e)
{
    Button button = (Button)sender;
    SetPLCVariable((string)button.Tag, true);
}

private void button_JogPLCVar_MouseUp(object sender, MouseEventArgs e
{
    Button button = (Button)sender;
    SetPLCVariable((string)button.Tag, false);
}

private void SetPLCVariable(string fieldName, bool value)
{
    Type type = typeof(PLCVars);
    FieldInfo fieldInfo = type.GetField(fieldName);
    fieldInfo.SetValue(PLCVariables, true);
}

Creating and subscribing all buttons

 panel1.Controls.Clear();

 for (int i = 1; i < 5; i++)
 {
     Button button = new Button();
     button.Name = "Button" + i;
     button.Tag = "PLCVar" + i;
     button.MouseUp += button_JogPLCVar_MouseUp;
     button.MouseDown += button_JogPLCVar_MouseDown;
     panel1.Controls.Add(button);
 }

NOTE: It's better to use properties instead of public fields. For properties you will need to use type.GetProperty method. Also it's better to use FlowLayoutPanel.