简体   繁体   中英

Reduce if else series in windows form checkedlistbox c#

In c#, in my windows form, I use a checkedListBox. So far in my checkedListBox I have 3 items. And 3 series of if/elseif statement.

I would like to implement a neat way of having specific actions depending on the combination of the items chosen. I was thinking on a binary tree.

Is a binary tree okay, or is there a method/property I do not know about in the checkedListBox that can help me?

Below is the current code :

private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        if (checkedListBox1.GetItemCheckState(0) == CheckState.Checked)
        {
            do_action_item0(current_parameters);
        }
        else if(checkedListBox1.GetItemCheckState(0) != CheckState.Checked)
        {
            undo_action_item0(previous_parameters);
        }

        if (checkedListBox1.GetItemCheckState(1) == CheckState.Checked)
        {
            do_action_item1(current_parameters);
        }
        else if (checkedListBox1.GetItemCheckState(1) != CheckState.Checked)
        {
            undo_action_item1(previous_parameters);
        }

        if (checkedListBox1.GetItemCheckState(2) == CheckState.Checked)
        {
            do_action_item2(current_parameters);
        }
        else if (checkedListBox1.GetItemCheckState(2) != CheckState.Checked)
        {
            undo_action_item2(previous_parameters);
        }
    }

Given you have multiple selections in checkbox list. You can try implementing Strategy pattern for this problem. Basically you need to create a strategy for each variant. You can read more on this here .

By implementing this you will be following the open close principle which means no matter how many items you wan to add later, your existing code will not need modification but will be open for extension.

First create yourself an enum like this:

public enum demo 
{
    none = 0,
    AOnly = 1,
    BOnly = 2,
    AandB = 3,
    COnly = 4,
    AandC = 5,
    BandC = 6,
    ABC = 7
}

Now on your action event you fill in an instance of your demo enum thus:

demo myDemo = demo.none;

if (checkedListBox1.CheckedItems.Contains("Option A"))
{
    myDemo = myDemo | demo.AOnly;
}
if (checkedListBox1.CheckedItems.Contains("Option B"))
{
    myDemo = myDemo | demo.BOnly;
}
if (checkedListBox1.CheckedItems.Contains("Option C"))
{
    myDemo = myDemo | demo.COnly;
}

Now you can have a switch statement so:

switch (myDemo)
{
    case demo.AOnly:
        MessageBox.Show("A Only");
        break;
    case demo.BOnly:
        MessageBox.Show("B Only");
        break;
    case demo.COnly:
        MessageBox.Show("C Only");
        break;
    case demo.AandB:
        MessageBox.Show("A and B");
        break;
    case demo.AandC:
        MessageBox.Show("A and C");
        break;
    case demo.BandC:
        MessageBox.Show("B and C");
        break;
    case demo.ABC:
        MessageBox.Show("ABC");
        break;
}

This illustrates the use of "OR"-ing items together. From three options, you can get 8 possibilities (2^3). All you need to do, is to make sure your "Principle" options are powers of two within your enumeration.

EDIT

Strongly related to this use of powers of 2 within an enum, is the flags attribute. For example:

[FlagsAttribute]
public enum demo2 
{
    none = 0,
    A = 1,
    B = 2,
    C = 4
}

This allows you to create an instance of the enum in the same way as before, but now you can use the syntax:

bool hasOptB = myDemo.HasFlag(demo2.B);

Depending on your circumstances, this might be more useful.

I would suggest that you introduce a flag enum that represents the items in the CheckedListBox .

[Flags]
enum ActionItemToPerform {
    None = 0, ActionItem0 = 1, ActionItem1 = 2, ActionItem2  = 4
}

Then create the items for the CheckedListBox based on these enum values:

CheckedListBox clb = new CheckedListBox();
foreach(var possibleAction in Enum.GetValues(typeof(ActionItemToPerform))){
   clb.Items.Add(possibleAction, false);
}

The binding to the Action to be performed based on these flags is encapsulated in a class:

public class ConditionalDoAction {

    // initialize this with the conditions when this shall be performed 
    public ActionItemToPerform Condition { get; set; }

    // TODO: tweak delegate to match your method signatures...
    public Action<CurrentParameters> Do { get; set; }
}

You initialize a list of these actions and the criteria when they shall be performed.

var configuredActions = new List<ConditionalDoAction>();
configuredActions.Add(new ConditionalDoAction  {
    Condition = ActionItemToPerform.ActionItem0,
    Do =  do_action_item0
});

You can give combinations of conditions by combining flags, eg

Condition = ActionItemToPerform.ActionItem0 & ActionItemToPerform.ActionItem1

When you read the checked items, create the cumulative flag state tally and compare with the configured actions:

btn.Click += delegate {
    ActionItemToPerform tally = ActionItemToPerform.None;
    foreach (var selectedAction in clb.CheckedItems) {
        tally |= selectedAction;
    }

    foreach(var configuredAction in configuredActions) {
        if (configuredAction.HasFlag(tally)) {
            configuredAction.Do(current_parameters);
        }
    }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM