A Different Approach to Flow Control and the Action Delegate

This originally started as a post about the Action delegate. But Recently on StackOverflow, I stumbled across an interesting technique for flow control which differs from the standard if/switch statements approach. The example I will show below uses the Action Delegate.

The Action delegate has a void return type and like many of the System delegates, it has a large number of overrides which cater for differing numbers of parameters:

In this example, I am using 2 different overrides of the Action delegate in conjunction with a couple of dictionaries. First up, I create the dictionaries:

    public partial class MainWindow : Window
    {
        private IDictionary<string, Action> clearControlsDelegateBucket;
        private IDictionary<string, Action<CanExecuteRoutedEventArgs>> buttonCanExecuteDelegateBucket;
        public MainWindow()
        {
            clearControlsDelegateBucket = new Dictionary<string, Action>(2, StringComparer.Ordinal)
                                              {
                                                  {"ClearTextBoxButton", ClearTextBox},
                                                  {"ClearAllControlsButton", ClearAllControls}
                                              };
            buttonCanExecuteDelegateBucket = new Dictionary<string, Action<CanExecuteRoutedEventArgs>>(2, StringComparer.Ordinal)
                                         {
                                             {"ClearTextBoxButton", TextBoxCanClear},
                                             {"ClearAllControlsButton", ControlsCanClear}
                                         };
            InitializeComponent();

The UI looks like this:

<Window x:Class="ActionDelegate.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ActionDelegate.CustomCommands" Title="MainWindow" Height="145" Width="225">
        
    <Window.CommandBindings>
        <CommandBinding Command="local:ClearUiControlCommand.ClearControls" CanExecute="CanClear" Executed="ClearControls_Executed"></CommandBinding>
    </Window.CommandBindings>        
        
    <Grid>
        <StackPanel>
            <CheckBox x:Name="CheckedCheckBox" Content="This is initially checked" IsChecked="True" Margin="10,2,10,2" />
            <TextBox x:Name="TextBoxWithText" Text="This text is here" Margin="10,0,10,2" />
            <Label x:Name="LabelWithText" Content="This label content is here" Margin="10,0,10,2" />
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <Button x:Name="ClearTextBoxButton" Width="100" Content="Clear TextBox" Command="local:ClearUiControlCommand.ClearControls" />
                <Button x:Name="ClearAllControlsButton" Width="100"  Content="Clear All Controls" Command="local:ClearUiControlCommand.ClearControls"  />
            </StackPanel>
        </StackPanel>        
    </Grid>
</Window>

As you can see, I have bound the 2 clear buttons, ClearTextBoxButton and ClearAllControlsButton, to the same command ClearUiControlCommand.ClearControls. The Executed property of that custom command is set to the handler ClearControls_Executed. So, if the button can execute, it runs the following code:

        private void ClearControls_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Button clickedButton = e.OriginalSource as Button;
            String buttonName = clickedButton.Name;

            clearControlsDelegateBucket[buttonName].Invoke();
        }

You can see there how it has accessed the relevant dictionary item by way of the key which we gave to it in the constructor. That key being the same as the name of the button which was clicked. I then invoke the Action delegate stored at that item in the collection.

So, there is an interesting alternative to conventional flow control, using the Action delegate and an IDictionary collection.

Get the code:

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>