c# - 委托(delegate)事件的模式

标签 c# wpf events design-patterns mvvm

我将 MVVM 用于桌面应用程序。我有一个名为 Calculator 的模型,它在自己的线程中进行非常昂贵的计算。 MainViewModel 引用 Calculator 并使用计算结果。 View 获取结果并显示它们。

The problem is, that the Calculator returns the calculation results by using an event. And I don't want to bind the view to the event from the Calculator because the used Calculator can change on runtime. As solution I have used the same event twice, which I don't like, has someone a better approach.

型号:

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

View 模型:

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

最佳答案

在 View 模型中实现INotifyPropertyChanged,这是数据变化时更新 View 的常用方式。它可以很好地与绑定(bind)一起工作(我认为可以使用 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"));
    }
}

关于c# - 委托(delegate)事件的模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42200052/

相关文章:

javascript - 为什么“"click, "按钮”由跨度处理?

c# - ListBoxItem 中的复杂 UI

wpf - 更改 WPF DatePicker 的字符串格式

c# - TextBlock 中动态字符串的 WPF 本地化

c# - 如何将关键事件从控件冒泡到窗体?

JQuery 监听多个事件,但只触发一次

c# - LINQ 组不工作

c# - 在泛型类 <T,U> 的方法中比较 T 的两个变量(从 C++ 到 C# 的代码移植)

c# - Developer 和 MSbuild 命令提示符之间有什么区别

c# - 使用 sdkImages 未找到 WP 8