使用的ICommand为消息模式
这个解决方案针对 分离关注的和单一职责原则
它可以让你跳过MVVM的RelayCommand模式。
如果您使用XAML,则可以引用具有单个命令类的命名空间。像这样:
xmlns:cmd="clr-namespace:MyProject"
然后全局或本地风格可以定义为如下所示。这使得所有按钮只使用一个传递按钮文本中的命令作为参数。大多数按钮使用文本作为上下文,但标签也可以使用。
<Style BasedOn="{StaticResource XDButton}" TargetType="{x:Type Button}">
<Setter Property="Command" Value="{StaticResource ResourceKey=cmd}"/>
<Setter Property="CommandParameter" Value="{Binding Content, RelativeSource={RelativeSource Self}}"/>
</Style>
您可以像这样为整个项目创建一个命令,注意'路由'基于按钮文本。的青睐命名约定优于配置“
public class Commands : ICommand
{
private bool canExecute = true;
public bool CanExecute(object parameter)
{
return canExecute;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
NotifyCanExecute(false);
var information = parameter.ToString();
try
{
if (information == "Show Passed") Events.ShowAllPassedTests(this, new EventArgs());
if (information == "Show Failed") Events.ShowAllFailedTests(this, new EventArgs());
if (information == "Sort By elapsed Time") Events.SortByElapsedTime(this, new EventArgs());
if (information == "Sort By Run Data") Events.SortByRunData(this, new EventArgs());
if (information == "Sort By Title") Events.SortByTitle(this, new EventArgs());
if (information == "Generate HTML Report") Events.GenerateHTMLReport(this, new EventArgs());
}
catch (NullReferenceException nre) {
Trace.WriteLine("Test Runner Commands 320- An attempt to fire an event failed due to no subscribers");
}
NotifyCanExecute(true);
}
private void NotifyCanExecute(bool p)
{
canExecute = p;
if (CanExecuteChanged != null) CanExecuteChanged(this, new EventArgs());
}
}
创建一个单一的活动聚集类是这样的:
public class Events
{
public static EventHandler ShowAllPassedTests;
public static EventHandler ShowAllFailedTests;
public static EventHandler ClearAllFilters;
public static EventHandler SortByElapsedTime;
public static EventHandler SortByRunData;
public static EventHandler SortByTitle;
public static EventHandler GenerateHTMLReport;
public static EventHandler<CheckBox> ColumnViewChanged;
}
您可以创建一个有按钮这样的分离型导航仪的用户控制。当按钮被点击时,它只是调用通过Button上下文的Command类。
<StackPanel Orientation="Vertical">
<StackPanel.Resources>
<Style BasedOn="{StaticResource XDButton}" TargetType="{x:Type Button}">
<Setter Property="Command" Value="{StaticResource ResourceKey=cmd}"/>
<Setter Property="CommandParameter" Value="{Binding Content, RelativeSource={RelativeSource Self}}"/>
</Style>
</StackPanel.Resources>
<Button x:Name="XBTNShowPassed" >Show Passed</Button>
<Button x:Name="XBTNShowFailed" >Show Failed</Button>
<Button x:Name="XBTNShowAll" >Show All</Button>
<Button x:Name="XBTNSortByElapsedTime" >Sort by Elapsed Time</Button>
<Button x:Name="XBTNSortByRunData" >Sort By Run Data</Button>
<Button x:Name="XBTNSortByTitle" >Sort By Title</Button>
<Button x:Name="XBTNGenerateHTMLReport" >Generate HTML Report</Button>
</StackPanel>
最后接收视图模型或其他类看起来是这样的:
Events.ColumnViewChanged += OnColumnViewChanged;
Events.SortByTitle += OnSortByTitle;
Events.SortByRunData += OnSortByRunData;
Events.SortByElapsedTime += OnSortByElapsedTime;
Events.GenerateHTMLReport += OnGenerateHTMLReport;
Events.ShowAllFailedTests += OnShowAllFailedTests;
Events.ShowAllPassedTests += OnShowAllPassedTests;
}
private void OnShowAllPassedTests(object sender, EventArgs e)
{
FilterCVS(tr => tr.DidTestPass);
}
private void OnShowAllFailedTests(object sender, EventArgs e)
{
FilterCVS(tr => tr.DidTestFail);
}
不要忘记实现Dispose
当代码挂接到事件处理程序变得没有资格垃圾采集。为了解决这个问题,实现Dispose模式和断开事件处理器...如
Events.OnColumnViewChanged -= OnColumnViewChanged;
如果您唯一关心的是可视性,您可以将它们抽象为部分类。但是,如果你需要很多命令,这可能暗示你的ViewModel尝试做太多。请记住,上面的解决方案可能会破坏你的viewmodels封装,因为上述命令只能访问公共属性和方法 – Tseng
你能提供一些更具体的哪些类型的命令吗?如果您尝试在ViewModel中投入太多关注点,或者您需要更好的抽象 – Tseng