簡體   English   中英

對組合框選擇的操作已更改

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM