在 MVVM 中指揮
命令用於在尊重 MVVM 模式的同時處理 WPF 中的 Events
。
正常的 EventHandler
看起來像這樣(位於 Code-Behind
):
public MainWindow()
{
_dataGrid.CollectionChanged += DataGrid_CollectionChanged;
}
private void DataGrid_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
//Do what ever
}
不能在 MVVM 中使用 Commands
:
<Button Command="{Binding Path=CmdStartExecution}" Content="Start" />
我建議為命令屬性使用某種字首(
Cmd
),因為你將主要在 xaml 中使用它們 - 這樣它們更容易識別。
因為它是 MVVM,你想要在你的 ViewModel
中處理那個命令(對於 Button``eq``Button_Click
)。
為此,我們基本上需要兩件事:
- System.Windows.Input.ICommand
- RelayCommand(例如從這裡獲取) 。
一個簡單的例子可能如下所示:
private RelayCommand _commandStart;
public ICommand CmdStartExecution
{
get
{
if(_commandStart == null)
{
_commandStart = new RelayCommand(param => Start(), param => CanStart());
}
return _commandStart;
}
}
public void Start()
{
//Do what ever
}
public bool CanStart()
{
return (DateTime.Now.DayOfWeek == DayOfWeek.Monday); //Can only click that button on mondays.
}
那麼這個細節是做什麼的:
ICommand
是 xaml 中的 Control
所繫結的。RelayCommand
將你的命令傳送到 Action
(即呼叫 Method
)。Null-Check 只確保每個 Command
只會初始化一次(由於效能問題)。如果你已經閱讀了上面 RelayCommand
的連結,你可能已經注意到 RelayCommand
對於它的建構函式有兩個過載。(Action<object> execute)
和 (Action<object> execute, Predicate<object> canExecute)
。
這意味著你可以(通常)新增第二個 Method
返回一個 bool
來告訴 Control
whehe事件可以發射或不發射。
一個好處是,如果 Method
將返回 false
,例如 Button
s 將是 false
CommandParameters
<DataGrid x:Name="TicketsDataGrid">
<DataGrid.InputBindings>
<MouseBinding Gesture="LeftDoubleClick"
Command="{Binding CmdTicketClick}"
CommandParameter="{Binding ElementName=TicketsDataGrid,
Path=SelectedItem}" />
</DataGrid.InputBindings>
<DataGrid />
在這個例子中,我想將 DataGrid.SelectedItem
傳遞給我的 ViewModel 中的 Click_Command。
你的方法應如下所示,而 ICommand 實現本身保持如上所述。
private RelayCommand _commandTicketClick;
public ICommand CmdTicketClick
{
get
{
if(_commandTicketClick == null)
{
_commandTicketClick = new RelayCommand(param => HandleUserClick(param));
}
return _commandTicketClick;
}
}
private void HandleUserClick(object item)
{
MyModelClass selectedItem = item as MyModelClass;
if (selectedItem != null)
{
//Do sth. with that item
}
}