我正在用 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
向您的观点公开了Progress
和Max
属性:
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中设置值属性。