C# 组合框选择的操作已更改
我正在使用MVVM将组合框绑定到ViewModel,对于繁重的操作和选择更改,我没有什么疑问 我想在所选项目发生更改时触发一些操作,我最初的方法是将逻辑放在所选项目绑定到的字段的setter中 所以我的第一个问题是,这是一个好的做法还是有更好的方法 这些操作在时间和资源上可能非常昂贵(需要通过web服务检索数据),我不希望UI冻结,因此最近我开始从集合中发送消息,该消息在视图的代码中接收,并异步调用ViewModel命令 我是在浪费时间还是这有什么意义 问题是,当我调试UI时,有时无论如何都会冻结(它不会在发布时发生)。阅读这里和那里,我知道它可能与调试器有关,有人能在VS 2015上确认这种行为吗 补充资料 应要求,我提供了一些例子。这是我的第一个方法: (XAML)C# 组合框选择的操作已更改,c#,wpf,mvvm,visual-studio-2015,combobox,C#,Wpf,Mvvm,Visual Studio 2015,Combobox,我正在使用MVVM将组合框绑定到ViewModel,对于繁重的操作和选择更改,我没有什么疑问 我想在所选项目发生更改时触发一些操作,我最初的方法是将逻辑放在所选项目绑定到的字段的setter中 所以我的第一个问题是,这是一个好的做法还是有更好的方法 这些操作在时间和资源上可能非常昂贵(需要通过web服务检索数据),我不希望UI冻结,因此最近我开始从集合中发送消息,该消息在视图的代码中接收,并异步调用ViewModel命令 我是在浪费时间还是这有什么意义 问题是,当我调试UI时,有时无论如何都会冻
(视图模型)
public class ViewModel
{
private MyObject _selectedField = null;
public MyObject SelectedField
{
get
{
return _selectedField;
}
set
{
if(_selectedField != value)
{
// Expensive action
_selectedField = value;
RaisePropertyChanged(() => SelectedField);
}
}
}
}
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
}
}
昂贵的操作会进行一些web服务调用,并且可能需要很长时间,这种设计好吗,或者有更好的方法来实现这一点
我的第二种方法是通过消息,如本例所示:(视图模型)
public class ViewModel
{
private MyObject _selectedField = null;
public MyObject SelectedField
{
get
{
return _selectedField;
}
set
{
if(_selectedField != value)
{
// Expensive action
_selectedField = value;
RaisePropertyChanged(() => SelectedField);
}
}
}
}
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
}
}
(代码隐藏)
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
Messenger.Default.Register(这个DoStuffMessage\u处理程序);
}
私有void DoStuffMessage_处理程序(DoStuffMessage msg)
{
(DataContext作为ViewModel.DoStuffCommand.Execute(null);
}
}
这种方法是更好的,还是仅仅是坏的和无用的?您可以在setter中做任何您喜欢的事情,只要它是异步的
private string _test;
public string Test
{
get { return _test; }
set
{
Task.Run(() =>
{
//do stuff
});
_test = value;
}
}
如果您不想在setter中放置逻辑,例如,因为违反了单一责任原则,那么您应该使用交互来捕获SelectionChange事件,并在VM中调用一个命令,该命令应该调用异步方法
这里有一个使用交互的示例:
就这样 对于MVVM,我更喜欢使用relayCommand将XAML中的EventTrigger绑定到viewmodel中的ICommand。我觉得这样做可以实现代码的最佳分离,并且比向setter添加大量逻辑更清晰,因为在故障排除过程中,这些逻辑可能会被忽略。以下是该过程的概述: 这是连接一个按钮并传递一个参数,因此显然您需要根据您的用例修改它,但它将显示基本技术。在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>
在您的虚拟机中:
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);
}
publicstaticicommand MyCommand{get;set;}//声明一个ICommand-绑定到这个!
公共主视图模型(IDataService数据服务)
{
//将ICommand与方法关联。如果不使用参数,则此处不需要lambda表达式。
MyCommand=新的RelayCommand((参数)=>MyCommand方法(参数));
}
public void myCommand方法(字符串参数)
{
WriteLine(“这是我想在我的虚拟机中运行的代码,参数是“+参数”);
}
我在我的应用程序中使用了[free]MVVMLight工具包,该工具包是由我链接到的文章作者编写的,但其中很多内容也被嵌入到了.Net中。使用Expression Blend可以在您进行设计时更轻松地连接这些内容。您的问题太广泛了。你有一些可以发布的代码和关于代码的具体问题吗?这也适用于SelectionChanged事件吗?没关系,@Dragosh Stoica回答说,但是你的answare有坦克。我还没有一个代码示例来准确说明你在做什么,但我认为这种方法只需对应用程序进行最小的更改即可工作。我担心这更像是一个性能问题,但如果只是违反原则,那也没什么大不了的。感谢您的回复。这是有效的,请注意,这将在任何更改测试(不仅仅是UI交互的更改)时运行。例如,当您加载viewmodel时,此代码将在测试设置为初始值后立即运行。这可能会产生意想不到的后果。