使用MVVM模式的忙指示器

3

这可能是一个重复的问题,但我找不到解决我的问题的方法。

我正在使用MVVM模式开发WPF应用程序。

有四个视图与它们的ViewModel绑定。所有的ViewModel都有BaseViewModel作为父类。

public abstract class ViewModelBase : INotifyPropertyChanged
{
    private bool isbusy;

    public bool IsBusy
    {
        get
        {
            return isbusy;
        }
        set
        {
            isbusy = value;
            RaisePropertyChanged("IsBusy");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

主视图包含繁忙指示器:

<extWpfTk:BusyIndicator IsBusy="{Binding IsBusy}">
        <ContentControl />
    </extWpfTk:BusyIndicator>

如果在MainViewModel中设置IsBusy = true,则会显示忙碌指示器。

如果我尝试从其他ViewModel设置IsBusy = true,则不会显示忙碌指示器。

需要注意的是,我不能在项目中使用第三方库,例如MVVMLight,以便使用它们的Messenger在ViewModel之间通信。

MainView:

public class MainWindowViewModel : ViewModelBase
{
    public ViewModel1 ViewModel1 { get; set; }
    public ViewModel2 ViewModel2 { get; set; }
    public ViewModel3 Model3 { get; set; }

    public MainWindowViewModel()
    {
        ViewModel1 = new ViewModel1();
        ViewModel2 = new ViewModel2();
        ViewModel3 = new ViewModel3();
        //IsBusy = true; - its working
    }
}

视图模型1:

public class ViewModel1 : ViewModelBase
{
    RelayCommand _testCommand;

    public ViewModel1()
    {
    }

    public ICommand TestCommand
    {
        get
        {
            if (_testCommand == null)
            {
                _testCommand = new RelayCommand(
                    param => this.Test(),
                    param => this.CanTest
                    );
            }
            return _testCommand;
        }
    }

    public void Test()
    {
        //IsBusy = true; - BusyIndicator is not shown

    }

    bool CanTest
    {
        get 
        { 
            return true; 
        }
    }
}

FYI,MVVMLight是开源的,你可以轻松提取Messenger实现并丢弃其余部分 - 直接在你的解决方案中拥有源代码,无需第三方库。 - Adam Houldsworth
@AdamHouldsworth 好吧,不知为何我在试图使用MVVMLight中的WeakReference类时遇到了SecurityException。我也尝试了Mediator模式,但是在使用WeakReference时同样出现了问题。 - Danilo Vulović
@GazTheDestroyer,其他四个视图中没有包含对MainView的引用。 - Danilo Vulović
那么这4个ViewModel如何应用到4个视图中呢?你是每次将MainView的DataContext设置为不同的ViewModel,还是这些视图完全独立,而MainView看不到它们的ViewModel? - GazTheDestroyer
@GazTheDestroyer 每个视图都有对应的ViewModel作为DataContext。MainViewModel引用了所有其他ViewModels。但是,所有ViewModels都从BaseViewModel继承了IsBusy属性。 - Danilo Vulović
1个回答

4
   public class MainWindowViewModel : ViewModelBase
   {
    public ViewModel1 ViewModel1 { get; set; }
    public ViewModel2 ViewModel2 { get; set; }
    public ViewModel3 Model3 { get; set; }

    public MainWindowViewModel()
    {
        ViewModel1 = new ViewModel1();
        ViewModel2 = new ViewModel2();
        ViewModel3 = new ViewModel3();
        ViewModel1.PropertyChanged += (s,e) => 
        {
           if(e.PropertyName == "IsBusy") 
           { 
              // set the MainWindowViewModel.IsBusy property here
              // for example:
              IsBusy = ViewModel1.IsBusy;
           }
         }
    //IsBusy = true; - its working
   }
}

重复订阅所有的ViewModel。

别忘了在不需要时取消事件订阅,以避免内存泄漏。

你的问题是:你绑定到了MainWindowViewModel的属性,而不是内部ViewModel的属性。


我绑定到了BaseViewModel属性,该属性从所有的ViewModel中都可见。如果我更改IsBusy属性,是否应该通知所有视图? - Danilo Vulović
1
不,绑定并不是魔法。您有4个实例:MainWindowViewModelViewModel1等,每个实例都有自己的IsBusy属性。当您将ViewModel1.IsBusy=true设置为真时,其他的IsBusy仍然为假。 - Anton Sizikov
当您在XAML中设置绑定时,您连接了MainWindowViewModel.IsBusy属性,并且它可以工作。但是您的视图无法检测到其他的IsBusy属性。因此,您必须手动通知视图。 - Anton Sizikov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接