[英]Action on ComboBox selection changed
我正在使用MVVM將ComboBox綁定到ViewModel,並且我對繁重的動作和選擇更改沒有任何疑問。
我想在更改所選項目時觸發一些操作,我的最初方法是將邏輯放入綁定到所選項目的字段的設置器中。
所以我的第一個問題是,這是好的做法還是有更好的方法?
這些操作可能會花費大量時間和資源(需要通過Web服務檢索數據),並且我不希望UI凍結,因此最近我已經開始從視圖中接收到的集合發送消息。代碼隱藏和異步調用ViewModel命令。
我只是在浪費時間,還是有意義?
問題是,當我調試UI時,有時無論如何都會凍結(在發行時未發生)。 在這里和那里閱讀,我發現它可能與調試器相關,誰能在VS 2015上確認這種行為?
附加信息
根據要求,我提供了一些示例。 這是我的第一種方法:
(XAML)
<ComboBox SelectedItem="{Binding SelectedField}"/>
(視圖模型)
public class ViewModel
{
private MyObject _selectedField = null;
public MyObject SelectedField
{
get
{
return _selectedField;
}
set
{
if(_selectedField != value)
{
// Expensive action
_selectedField = value;
RaisePropertyChanged(() => SelectedField);
}
}
}
}
昂貴的操作會調用一些Web服務,並且可能會花費很長時間,這是好的設計還是有更好的方法來實現呢?
我的第二種方法是通過消息,如本示例所示:
(視圖模型)
public class ViewModel
{
private MyObject _selectedField = null;
public MyObject SelectedField
{
get
{
return _selectedField;
}
set
{
if(_selectedField != value)
{
Messenger.Default.Send(new DoStuffMessage());
_selectedField = value;
RaisePropertyChanged(() => SelectedField);
}
}
}
private RelayCommand _doStuffCommand = null;
public ICommand DoStuffCommand
{
get
{
if (_doStuffCommand == null)
_doStuffCommand = new RelayCommand(async () => await DoStuff());
return _doStuffCommand;
}
}
private async Task DoStuff()
{
// Expensive action
}
}
(代碼隱藏)
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Messenger.Default.Register<DoStuffMessage>(this, DoStuffMessage_Handler);
}
private void DoStuffMessage_Handler(DoStuffMessage msg)
{
(DataContext as ViewModel).DoStuffCommand.Execute(null);
}
}
這是更好的方法,還是不好且沒有用?
對於MVVM,我更喜歡使用RelayCommands將XAML中的EventTrigger綁定到視圖模型中的ICommand。 我覺得這可以最好地分離代碼,並且比在設置器中添加很多邏輯更清晰,因為在設置問題時可能會忽略這些邏輯。 以下是該過程的概述: https : //msdn.microsoft.com/zh-cn/magazine/dn237302.aspx
這是為了連接一個按鈕並傳遞一個參數,因此顯然您需要針對您的用例進行修改,但這將顯示基本技術。 在XAML中:
<Button Content="Click Me">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<Custom:EventToCommand Command="{Binding MyCommand}" CommandParameter="foo"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
在您的VM中:
public static ICommand MyCommand { get; set; } // declare an ICommand - bind to this!
public MainViewModel(IDataService dataService)
{
// associate your ICommand with a method. If you don't use a parameter, you don't need the lambda expression here.
MyCommand = new RelayCommand<string>((paramater) => MyCommandMethod(parameter));
}
public void MyCommandMethod(string parameter)
{
Debug.WriteLine("This is the code I want to run in my VM. The parameter is " + parameter);
}
我為我的應用程序使用了[免費] MVVMLight工具包,該工具包是由撰寫我所鏈接的文章的人所寫的,但是其中很多內容也都包含在.Net中。 在設計時,使用Expression Blend可以更輕松地連接這些東西。
您可以在setter中做任何您想做的事情,只要它是異步的即可。
private string _test;
public string Test
{
get { return _test; }
set
{
Task.Run(() =>
{
//do stuff
});
_test = value;
}
}
如果您不想在setter中放置邏輯,例如由於違反了“單一職責”原則,則應使用交互來捕獲SelectionChange事件,並在VM中調用一個應調用異步方法的命令。
在這里,您有一個使用交互的示例: 可愛鏈接
而已!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.