一键绑定两个命令 WPF/MVVM

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22803913/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 11:26:03  来源:igfitidea点击:

Binding two commands in one button WPF/MVVM

wpfmvvmbrowsercommand

提问by Alaa'

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?

您知道如何绑定 1 个按钮的两个命令吗?

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

我正在使用 MVVM,而且我是 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:

这是 WPFBrowser.cs 代码:

         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

回答by Sheridan

You want to click one Buttonand 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:

您想单击一个Button并运行两段代码……听起来确实没有那么复杂。使用可用的RelayCommands 之一,可以像这样简单地解决问题:

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

In XAML:

在 XAML 中:

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

ActionCommandis my own form of the RelayCommand, but all of the delegate ICommandimplementations are roughly equal and could work in this way. The CommandParametervalue comes into the code as the actionvariable and is passed through to the two functions.

ActionCommand是我自己的 形式RelayCommand,但所有的delegate ICommand实现都大致相同,并且可以以这种方式工作。该CommandParameter值作为action变量进入代码并传递给两个函数。

回答by Golvellius

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

您可以使用CompositeCommand棱镜框架。在您的视图模型中创建一个额外的 CompositeCommand,使用此 CompositeCommand 注册两个普通命令并将按钮绑定到 CompositeCommand。

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

有关如何使用 CompositeCommands 的信息,请参阅第 130 页的Prism 文档

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

您的应用程序需要引用包含在 Prism 包中的 Microsoft.Practices.Prism.dll。