WPF MVVM 报告来自另一个类的进度?



我正在用 C# WPF 开发一个应用程序,要求是使用 MVVM 模式,但我正在努力查找有关如何向进度条报告进度条的信息,进度值来自另一个类,我将尝试用代码更好地解释自己。

主窗口VieModel.cs

//...
//...
public void StartSearch(object obj)
{
search.SearchByName(string a); //CALL TO THE METHOD IN THE SEARCH CLASS
}
//...
//...

搜索.cs

public string SearchByName(string searchString){
//..
//..
for (int i = 0;i <x;i++)
{
//HERE I NEED TO REPORT I AS PROGRESS VALUE
}
}

MainWindow.xaml.cs我将MainWindowViewModel绑定为DataContext。

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
}

这甚至有可能实现我想要的东西吗?

这当然是可能的。您需要做的是在Search课程中设置一个事件:

public event Action<int> ProgressChanged;

然后设置要在循环中引发的事件:

public string SearchByName(string searchString){
for (int i = 0; I < x; i++)
{
//...
ProgressChanged?.Invoke(i);
}
}

然后在您的MainWindowVieModel中订阅该事件。执行此操作的一个好地方是构造函数:

public class MainWindowVieModel()
{
Search.ProgressChanged += UpdateValueInProgressBar(i);
}

最后,您必须使StartSearch方法async,以免冻结您的 UI:

public async void StartSearch(object obj)
{
await Task.Run(() => search.SearchByName(string a);
}

请注意,您实际上并不需要UpdateValueInProgressBar(),我只是将其留在那里,供您决定如何在自己的类中完成与 XAML 的绑定。

如果您有任何问题,请提问!我希望这对你有所帮助。

编辑:请注意,正如Vernari@Mario评论的那样,取消订阅该事件是防止内存泄漏的好主意。您必须决定在应用程序中的位置执行此操作。一个可能的解决方案可能是在方法本身中执行此操作:

public async void StartSearch(object obj)
{
Search.ProgressChanged += UpdateValueInProgressBar();
await Task.Run(() => search.SearchByName(string a);
Search.ProgressChanged -= UpdateValueInProgressBar();
}

编辑:您请求了UpdateValueInProgressBar方法的示例。我将假设您的MainWindowVieModel向您的观点公开了ProgressMax属性:

public class MainWindowVieModel
{
private int _Progress;
public int Progress
{
get => _Progress;
set { _Progress = value; NotifyPropertyChanged(); }
}
}

并在 XAML 中绑定到该属性:

<ProgressBar Minimum="0" Maximum="100" Value="{Binding Progress}" />

当然,这只是一个例子。在您的应用程序中,您还需要一种方法来了解您期望的i的最大值是多少(此处设置为 100(。 这些答案真的是为了给你一点方向。由你来解决你的特定方案。

没有足够的信息,因为问题是知道什么是"最佳"解决方案。

事件表示强引用,由于内存泄漏的风险,通常被认为是一个坏主意。 弱事件旨在避免这种情况,但并不那么简单。

以下是其他一些:

Mvvmlight messenger

https://social.technet.microsoft.com/wiki/contents/articles/26070.communicating-between-classes.aspx 或棱镜事件聚合器。两者都使用弱事件。棱镜涉及传递对桥接对象的引用。

绑定值

可以将 SearchVM 实例公开为主视图模型中的属性或主窗口视图模型中的属性,并将其绑定到进度栏上的值。在 SearchVM 中设置它,直接或间接地将操作从搜索虚拟机传递到搜索中。 也许有一个单独的搜索类有点毫无意义。不知道。

自定义路由事件

根据调用搜索的位置,可能会有一些用户控件。这可以引发路由事件,此进度条的父级可以侦听此事件。驱动路由事件将是用户控件的依赖项属性。我们不知道封装和可重用是否值得。

通过依赖注入传递引用

这是绑定的变体。

主窗口视图模型的一个属性可以是progressVM.cs。这可能是通过 DI 提供的单例。在任何给定时间点可能只有一个进度要显示。 将进度条的值绑定到进度虚拟机的属性。通过 DI 将进度 vm 传递到搜索中。在搜索.cs中设置值属性。

最新更新