Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 组合框选择的操作已更改_C#_Wpf_Mvvm_Visual Studio 2015_Combobox - Fatal编程技术网

C# 组合框选择的操作已更改

C# 组合框选择的操作已更改,c#,wpf,mvvm,visual-studio-2015,combobox,C#,Wpf,Mvvm,Visual Studio 2015,Combobox,我正在使用MVVM将组合框绑定到ViewModel,对于繁重的操作和选择更改,我没有什么疑问 我想在所选项目发生更改时触发一些操作,我最初的方法是将逻辑放在所选项目绑定到的字段的setter中 所以我的第一个问题是,这是一个好的做法还是有更好的方法 这些操作在时间和资源上可能非常昂贵(需要通过web服务检索数据),我不希望UI冻结,因此最近我开始从集合中发送消息,该消息在视图的代码中接收,并异步调用ViewModel命令 我是在浪费时间还是这有什么意义 问题是,当我调试UI时,有时无论如何都会冻

我正在使用MVVM将组合框绑定到ViewModel,对于繁重的操作和选择更改,我没有什么疑问

我想在所选项目发生更改时触发一些操作,我最初的方法是将逻辑放在所选项目绑定到的字段的setter中

所以我的第一个问题是,这是一个好的做法还是有更好的方法

这些操作在时间和资源上可能非常昂贵(需要通过web服务检索数据),我不希望UI冻结,因此最近我开始从集合中发送消息,该消息在视图的代码中接收,并异步调用ViewModel命令

我是在浪费时间还是这有什么意义

问题是,当我调试UI时,有时无论如何都会冻结(它不会在发布时发生)。阅读这里和那里,我知道它可能与调试器有关,有人能在VS 2015上确认这种行为吗

补充资料

应要求,我提供了一些例子。这是我的第一个方法:

(XAML)

(视图模型)

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时,此代码将在测试设置为初始值后立即运行。这可能会产生意想不到的后果。