Binding two commands to one button?
Asked Answered
F

4

9

I have a tab control contains two tabs, one shows me the messages of a running process and the other shows me a web page!

I have three buttons (start, stop and clear) when I press start the process run and the messages show up.

What I need is wen I press Start button, both tabs, shows me the required content. That's mean I need two bind two commands to the same button

Do you know how to bind for 1 button two commands?

I'm using MVVM, and I'm new in MVVM.

<Button Content="Start" Command="{Binding StartProcess_Command }" Height="25" Width="60" Grid.Row="0" Grid.Column="0" Margin="10"/>
<Button Content="Stop"  Command="{Binding StopProcess_Command}" Height="25" Width="60" Grid.Row="0" Grid.Column="1" Margin="10"/>
<Button Content="Clear" Command="{Binding ClearBtn_Command}" Height="25" Width="60" Grid.Row="0" Grid.Column="2" Margin="10"/>
<telerik:RadTabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  Grid.Row="1" Grid.ColumnSpan="4" Margin="10">
    <telerik:RadTabItem Header="Maestro" IsSelected="{Binding Path=MaestroSelected}">
        <ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible">
            <local:WPFBrowser/>
        </ScrollViewer>
    </telerik:RadTabItem>
    <telerik:RadTabItem Header="Messages">
        <Grid Background="LightGray">
            <ScrollViewer VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible">
                <TextBlock TextWrapping="Wrap" Text="{Binding Path=output_process,UpdateSourceTrigger=Default}"/>
            </ScrollViewer>
        </Grid>
    </telerik:RadTabItem>
</telerik:RadTabControl >

And this is the WPFBrowser.cs code:

         public WPFBrowser()
            {
                ServerString = "localhost"; //defualt value
                PortString = "9999"; //default value
                this.refreshCommand = new Lunch_Maestro.ViewModel.Command(DoRefreshCommand);
                m_WPFBrowser = new WebBrowser()
                {
                    HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
                    VerticalAlignment = System.Windows.VerticalAlignment.Stretch
                };

                m_WPFBrowser.Navigated += WPFBrowser_Navigated;

                this.Content = m_WPFBrowser;
            }

            private void WPFBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
            {
                this.HideScriptErrors(m_WPFBrowser, true);
            }


            /// <summary>
            /// Found this link with interesting scenerios for script erros...
            /// http://social.msdn.microsoft.com/Forums/vstudio/en-US/4f686de1-8884-4a8d-8ec5-ae4eff8ce6db/new-wpf-webbrowser-how-do-i-suppress-script-errors?forum=wpf
            /// </summary>
            public void HideScriptErrors(WebBrowser wb, bool Hide)
            {
                FieldInfo fiComWebBrowser = typeof(WebBrowser).GetField("_axIWebBrowser2", BindingFlags.Instance | BindingFlags.NonPublic);
                if (fiComWebBrowser == null) return;

                object objComWebBrowser = fiComWebBrowser.GetValue(wb);

                if (objComWebBrowser == null) return;

                objComWebBrowser.GetType().InvokeMember("Silent", BindingFlags.SetProperty, null, objComWebBrowser, new object[] { Hide });

            }


            private void DoRefreshCommand()
            {
                m_WPFBrowser.Navigate(new Uri("http://" + ServerString + ":" + PortString + "/"));
            }

            private bool _maestroSelected;
            public bool MaestroSelected
            {
                get { return _maestroSelected; }
                set
                {
                    _maestroSelected = value;
                    if (_maestroSelected == true)
                        m_WPFBrowser.Navigate(new Uri("http://" + ServerString + ":" + PortString + "/"));
                    OnPropertyChanged("MaestroSelected");
                }
            }

            private readonly WebBrowser m_WPFBrowser;

            private string _serverString;
            public string ServerString
            {
                get { return _serverString; }
                set
                {
                    _serverString = value;
                    OnPropertyChanged("ServerString");
                }
            }

            private string _portString;
            public string PortString
            {
                get { return _portString; }
                set
                {
                    _portString = value;
                    OnPropertyChanged("PortString");
                }
            }

            private Lunch_Maestro.ViewModel.Command refreshCommand;
            public Lunch_Maestro.ViewModel.Command RefreshCommand
            {
                get { return refreshCommand; }
            }
// and Inotify property changes here
Foreandaft answered 2/4, 2014 at 7:7 Comment(1)
Take a look at this: codeproject.com/Articles/990113/…Bibliolatry
O
13

you can call multiple commands like this:

// xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

<Button>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <i:InvokeCommandAction Command="{Binding Cmd1}" />
            <i:InvokeCommandAction Command="{Binding Cmd2}" />
            <i:InvokeCommandAction Command="{Binding Cmd3}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

this will also allow you to control the command execution order if you ever need to

PS: you just need to install Microsoft.Xaml.Behaviors.Wpf NuGet package.

Onanism answered 13/3, 2021 at 20:57 Comment(0)
S
8

You want to click one Button and run two pieces of code... it really doesn't sound that complicated. Using one of the available RelayCommands, the problem could be fixed as simply as this:

public ICommand SomeCommand
{
    get { return new ActionCommand(action) => { RunFirstFunction(action); 
        RunSecondFunction(action) }, canExecute => someCondition); }
}

In XAML:

<Button Command="{Binding SomeCommand}" CommandParameter="{Binding SomeObject}">
    Click Me
</Button>

ActionCommand is my own form of the RelayCommand, but all of the delegate ICommand implementations are roughly equal and could work in this way. The CommandParameter value comes into the code as the action variable and is passed through to the two functions.

Secularism answered 2/4, 2014 at 8:8 Comment(0)
B
3

You could use the CompositeCommand from the Prism Framework. Create an additional CompositeCommand in your viewmodel, register both ordinary commands with this CompositeCommand and bind the button to the CompositeCommand.

See the Prism documentation on page 130 on how to work with CompositeCommands.

Your app needs to reference Microsoft.Practices.Prism.dll which is included in the Prism package.

Bianchi answered 2/4, 2014 at 7:58 Comment(0)
B
1

Another approach is with WPF, buttons can easily do two things - by the Click event and the Command event. Limitation: only two things. Advantage: Using the power of the standard button so you need no other NuGet packages or third party references.

In your Xaml:

<Button Style="{StaticResource CancelButtonStyle}"
        Command="{Binding CancelScenarioCommand}"
        Click="On_Close_Button" />

In your Xaml.cs code behind:

private void On_Close_Button(object sender, RoutedEventArgs e)
{
    Close();
}

In your ViewModel (VM):

public ICommand CancelScenarioCommand { get; }

public ThisViewModel()
{
   CancelScenarioCommand = new RelayCommand(OnCancelScenario);
}

private void OnCancelScenario()
{
    // do something spectacular
}
Binni answered 20/3, 2023 at 16:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.