2017-02-13 75 views
1

我將MVVM用於桌面應用程序。我有一個名爲Calculator的模型,它在自己的線程中執行非常昂貴的計算。 MainViewModel引用Calculator並使用計算結果。該視圖獲取結果並顯示它們。委派事件的模式

問題是,Calculator通過使用事件返回計算結果。而且我不想將視圖綁定到Calculator,因爲使用的Calculator可以在運行時更改。作爲解決方案,我已經使用了兩次相同的事件,我不喜歡這種事件,但有人提出了更好的方法。

型號:

public class Calculator 
{ 
    public event CalculatedHandler Calculated; 
    public delegate void CalculatedHandler(object sender, IEnumerable<string> values); 

    protected void OnCalculated(IEnumerable<string> values) 
    { 
     Calculated?.Invoke(this, values); 
    } 

    public void Run() 
    { 
     BackgroundWorker bw = new BackgroundWorker(); 
     bw.DoWork += new DoWorkEventHandler(Calculate); 
    } 

    private void Calculate(object sender, DoWorkEventArgs e) 
    { 
     List<string> values = new List<string>(); 
     for (int i = 0; i < 10000; i++) 
     { 
      // Do expensive stuff 
      values.Add(i + ""); 
      OnCalculated(values); 
     } 
    } 
} 

視圖模型:

public class CalculatorViewModel 
{ 
    private Calculator calculator; 

    public event CalculatedHandler Calculated; 
    public delegate void CalculatedHandler(object sender, IEnumerable<string> values); 

    protected void OnCalculated(IEnumerable<string> values) 
    { 
     Calculated?.Invoke(this, values); 
    } 

    public CalculatorViewModel() 
    { 
     calculator = new Calculator(); 
     calculator.Calculated += Calculator_Calculated; 
    } 

    private void Calculator_Calculated(object sender, IEnumerable<string> values) 
    { 
     OnCalculated(values); 
    } 
} 

查看XAML:

<Window.DataContext> 
    <viewmodels:CalculatorViewModel /> 
</Window.DataContext> 

查看後面的代碼:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     DataContextChanged += MainWindow_DataContextChanged; 
    } 

    private void MainWindow_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 
    { 
     CalculatorViewModel viewModel = e.NewValue as CalculatorViewModel; 

     viewModel.Calculated += ViewModel_Calculated; 
    } 

    private void ViewModel_Calculated(object sender, IEnumerable<string> values) 
    { 
     // Draw values on the canvas 
    } 
} 
+0

在模型和視圖模型中使用[異步/等待](https://msdn.microsoft.com/en-us/library/mt674882.aspx)。 – Clemens

+0

@Clemens你能給我一個關於 –

+0

以上代碼的例子對不起,你可以在閱讀我已經鏈接的artice後輕鬆地做到這一點。 – Clemens

回答

3

在視圖模型,這是更新視圖數據更改時的常用方法執行INotifyPropertyChanged。它可以很好地與綁定一起工作(我認爲可以使用ItemsControlCanvas作爲它的面板來顯示沒有代碼隱藏的計算結果)。

public class CalculatorViewModel: INotifyPropertyChanged 
{ 
    private Calculator calculator; 

    public event PropertyChangedEventHandler PropertyChanged; 

    public IEnumerable<string> CalcValues { get; set; } 

    public CalculatorViewModel() 
    { 
     calculator = new Calculator(); 
     calculator.Calculated += Calculator_Calculated; 
    } 

    private void Calculator_Calculated(object sender, IEnumerable<string> values) 
    { 
     CalcValues = values; 
     PropertyChanged?.(this, new PropertyChangedEventArgs("CalcValues")); 
    } 
} 
+0

好的,但我必須綁定到來自視圖後面的代碼中的'CalcValues',以便繪製值等是可能的 - 這是您的意思嗎? –

+1

@KevinWallis,我記得像''在xaml中,而不是在代碼隱藏;和ItemsControl + Canvas組合顯示在這裏:http://stackoverflow.com/questions/1265364/setting-canvas-properties-in-an-itemscontrol-datatemplate。您也可以繼續使用後面的代碼方法,但不是'Calculated'事件訂閱'PropertyChanged' – ASh

+0

Thx提示! –