![](/img/trans.png)
[英]MVVM Light: About extracting the RelayCommand navigation parameter
[英]Dynamically assigning a parameter to a RelayCommand in MVVM Light
我已經看到了很多使用MVVM Light中的RelayCommand類通過命令傳遞參數的示例,但是我想要的和所見之間有一些細微的差別。
我想創建一些按鈕,使它們都具有關聯的ModuleType。 當他們執行動作時,我想知道它是哪個ModuleType。 而且我想以一種代碼有效的方式執行此操作,因此不必手動創建RelayCommands,而是在foreach循環中執行所有操作,這還因為我不知道在開始時必須創建多少個按鈕。
所以這是代碼。 在我的ViewModel中
public ModuleSelectionViewModel(MachineStatusModel model, int order, List<ModuleType> modules) : base(model)
{
........
// create button for each of the modules
foreach (ModuleType mod in modules)
{
_navBarButtons.Add(new NavButton(mod.ToString(), new RelayCommand<ModuleType>(exec => ButtonExecute(mod)), mod));
}
RaisePropertyChanged("NavBarButtons");
}
// Binding to the Model
public ObservableCollection<NavButton> NavBarButtons
{
get { return _navBarButtons; }
}
// Execut Action
public void ButtonExecute(ModuleType mod)
{
WriteToLog("Selected " + mod.ToString());
}
// Support class
public class NavButton
{
public string ButtonContent { get; set; }
public ICommand ButtonCommand { get; set; }
public ModuleType ButtonModuleType;
public NavButton(string content, ICommand relay, ModuleType moduleType)
{
this.ButtonContent = content;
this.ButtonCommand = relay;
this.ButtonModuleType = moduleType;
}
}
我仍在學習lambda表達式,所以我想我在RelayCommand的初始化上做錯了。
如果執行foreach
循環並在lambda表達式中使用loop變量,則將其捕獲。 不幸的是,變量的作用域不正確(至少在C#的較早版本中,此變化隨C#5的變化而變化 (感謝Mafii))。
因此,您需要執行以下操作:
foreach (ModuleType mod in modules)
{
// New variable that is locally scoped.
var type = mod;
_navBarButtons.Add(new NavButton(mod.ToString(),
new RelayCommand<ModuleType>(param => ButtonExecute(type)), type));
}
關於HB發布的解決方案:不知道為什么它不能與lambda函數一起使用,為什么在按下按鈕時不執行ButtonExecute。 而且我也不理解在foo為空並傳遞給該函數時定義lambda函數(如“ foo => ButtonExecute(foo)”)的邏輯。 但無論如何...
這是我所做的並且正在工作:
模型
<ItemsControl Name="NavButtonsItemsControl" ItemsSource="{Binding NavBarButtons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding ButtonContent}" CommandParameter="{Binding ButtonModuleType}" Command="{Binding ButtonCommand}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
ViewModel (檢查我的初始問題中的其余代碼)
.........
_navBarButtons.Add(new NavButton(mod.ToString(), new RelayCommand<ModuleType>(ButtonExecute), type));
.........
private void ButtonExecute(ModuleType state)
{
WriteToLog("Command with parameter " + state.ToString());
}
您可以使用Object而不是ModuleType使其更通用。 解決方案不是使用lambda函數,而是在按鈕中定義CommandParameter綁定,並將該值作為execute函數中的參數。 我認為綁定沒有明確定義,這就是為什么我很難理解該值如何達到“ ButtonExecute”的原因,但是按照Dominik Schmidt教程中的步驟進行工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.