使用 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;
}
您可以像这样创建一个带有按钮的解耦 Navigator 用户控件。单击按钮时,它只调用传递 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>
最后接收的 ViewModel 或其他类看起来像这样:
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
当代码连接到 EventHandler 时,它就没有资格进行垃圾收集了。要解决此问题,请实现 Dispose 模式并断开事件处理程序...例如
Events.OnColumnViewChanged -= OnColumnViewChanged;