2017-01-10 6 views
2

私はMVVMを使用してComboBoxをViewModelにバインドしています。重いアクションと選択の変更についてはほとんど質問がありません。ComboBox選択のアクションが変更されました

選択したアイテムが変更されたときに、いくつかのアクションをトリガーしたいと思っていました。最初の方法は、選択したアイテムがバインドされているフィールドのセッターにロジックを配置することでした。

私の最初の質問は、この良い習慣であるか、より良いアプローチがあるということですか?

これらのアクションは、時間とリソース(Webサービスを通じてデータを取得する必要があります)が非常に高額になる可能性があり、UIがフリーズしないようにするため、最近私はセットからメッセージを送信し始めました。ビューのコードビハインドで受信され、ViewModelコマンドを非同期に呼び出します。

私は時間を無駄にしていますか、これは意味がありますか?

問題は、私がデバッグしているときにUIがフリーズすることがあることです(リリース時には発生しません)。私はそれがデバッガに関連する可能性があることを知って来たここで読んで、誰もVS 2015でこの動作を確認できますか?

要求などの追加情報

私はいくつかの例を提供しています。これが私の最初のアプローチです:

(XAML)
<ComboBox SelectedItem="{Binding SelectedField}"/>

(ViewModelに)

public class ViewModel 
{ 
    private MyObject _selectedField = null; 
    public MyObject SelectedField 
    { 
     get 
     { 
      return _selectedField; 
     } 
     set 
     { 
      if(_selectedField != value) 
      { 
       // Expensive action 
       _selectedField = value; 
       RaisePropertyChanged(() => SelectedField); 
      } 
     } 
    } 
} 

高価なアクションは、いくつかのWebサービスの呼び出しを行うと長いかかる場合があり、この設計であります良いか、これを達成する良い方法がありますか?

私の第二のアプローチは、この例のようにメッセージを介して、次のとおりです。
(ViewModelに)

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); 
    } 

} 

が良く、このアプローチですかちょうど悪く無用ですか?

+2

あなたの質問は広すぎます。投稿できるコードがいくつかあり、そのコードについて具体的な質問がありますか? – wdosanjos

答えて

1

asyncであれば、セッターで好きなことをすることができます。

private string _test; 
    public string Test 
    { 
     get { return _test; } 
     set 
     { 
      Task.Run(() => 
      { 
       //do stuff 
      }); 
      _test = value; 
     } 
    } 

あなたは、セッターのロジックを置くために、たとえば単一責任の原則に違反しているため、あなたはSelectionChangeイベントをキャッチするために相互作用を使用して、非同期メソッドを呼び出す必要がありますVMでコマンドを呼び出す必要がありますしたくない場合。ここで

あなたは相互作用を使用するサンプルがあります:cute link

それです!

+0

これはパフォーマンス上の問題ではないかと心配しましたが、それが大きな問題ではない原則違反だとしたら、あなたの答えをありがとう。 –

+0

これは有効です。これは、何らかの変更がテスト(UIのやりとりからの変更だけでなく)を実行するときに実行されることに注意してください。たとえば、ViewModelをロードすると、Testが初期値に設定されるとすぐにこのコードが実行されます。それは意図しない結果をもたらす可能性があります。 –

2

MVVMでは、RelayCommandsを使用してXAMLのEventTriggerをviewmodelのICommandにバインドすることをお勧めします。私はこれがコードの最適な分離を作成し、トラブルシューティング中に見落とされる可能性のある設定者に多くのロジックを追加するよりもはっきりしていると感じています。 https://msdn.microsoft.com/en-us/magazine/dn237302.aspx

これは、ボタンを配線してパラメータを渡すためのものです。したがって、あなたのユースケースに合わせて変更する必要がありますが、基本的なテクニックが表示されます。 XAMLでは:

あなたのVMで
<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); 
} 

私は私がリンク先の記事を書いた人によって書かれた私のアプリケーションのための[無料] MVVMLightツールキットを使用しますが、これの多くは.Netにも焼き付けられています。 Expression Blendを使用すると、デザイン時にこのようなものを簡単に配線することができます。

+0

これはSelectionChangedイベントでも機能しますか? –

+0

Nevermind、@Dragosh Stoicaはそれに答えましたが、あなたのansware用のタンクです。 –

+0

あなたが行っている作業のためのコードサンプルを用意していませんでしたが、このアプローチはアプリケーションの変更を最小限に抑えて動作すると思います。 –

関連する問題