一个视图模型用于多个按钮

本文关键字:用于 模型 按钮 一个 视图 | 更新日期: 2023-09-27 18:16:53

我是WPF和MVVM的新手。我试图理清如何有一个干净的项目结构,其中有多个按钮启动不同的应用程序(如chrome, IE,记事本)。是否有可能有一个ViewModel多个按钮?

我已经开始使用这里的代码,我在一个解决方案的尝试是使代码从该链接的视图模型基础,并有其他视图模型的每个按钮扩展说基础。

每一个都有一个独特的动作:

    public override void ClickAction()
    {
        Process ieProcess = new Process();
        ieProcess.StartInfo.FileName = "IExplore.exe";
        ieProcess.Start();
    }

然而,我不确定正确的方法去做这件事。我如何用这种方法创建一个DataContext ?

一个视图模型用于多个按钮

每个View应该有一个View Model;不是视图中的每个项目(在本例中为按钮)。做你所描述的一个简单的方法是使用CommmandParameter属性来传递你的exe名称:

<Button Content="Launch IE" Command="{Binding LaunchAppCommand}" CommandParameter="IExplorer.exe"/>
<Button Content="Launch Notepad" Command="{Binding LaunchAppCommand}" CommandParameter="notepad.exe"/>
<Button Content="Launch Chrome" Command="{Binding LaunchAppCommand}" CommandParameter="chrome.exe"/>

与您的命令:

public ICommand LaunchAppComand {get; private set;}
...
public MyViewModel()
{
    LaunchAppCommand = new DelegateCommand(LaunchApp);
}
...
private void LaunchApp(object parameter)
{
     string processName = (string)parameter;
     Process launchProc = new Process();
     launchProc.StartInfo.FileName = processName;
     launchProc.Start();
}

为了避免硬编码所有按钮,您可以使用ItemsControl,它为它创建的每个模板设置单独的数据上下文。为此,您需要一个数据类集合,以及一种稍微不同的方式来访问命令:

//ProcessShortcut.cs
public class ProcessShortcut
{
    public string DisplayName {get; set;}
    public string ProcessName {get; set;}
}
//MyViewModel.cs, include the previous code
//INotifyPropertyChanged left out for brevity
public IEnumerable<ProcessShortcut> Shortcuts {get; set;} 
public MyViewModel()
{
    Shortcuts = new List<ProcessShortcut>()
    {
        new ProcessShortcut(){DisplayName = "IE", ProcessName="IExplorer.exe"},
        new ProcessShortcut(){DisplayName = "Notepad", ProcessName="notepad.exe"},
        new ProcessShortcut(){DisplayName = "Chrome", ProcessName="chrome.exe"},
    };
}
//MyView.xaml
<Window x:Name="Root">
...
   <ItemsControl ItemsSource="{Binding Shortcuts}">
      <ItemsControl.ItemTemplate>
          <DataTemplate>
              <Button Content="{Binding DisplayName, StringFormat='{}Start {0}'}" 
                      Command="{Binding ElementName=Root, Path=DataContext.LaunchAppCommand}" 
                      CommandParameter="{Binding ProcessName}"/>
          </DataTemplate>
      </ItemsControl.ItemTemplate>
   </ItemsControl>
...
</Window>

因为ItemsControl将模板中的DataContext设置为绑定项,所以您需要ElementName绑定才能获得命令,并且不需要限制对ProcessShortcut成员的访问。从长远来看,当您有这样的重复控件时,这是您通常想要采用的方法。