【问题标题】:BusyIndicator using MVVMBusyIndi​​cator 使用 MVVM
【发布时间】:2012-09-05 05:27:49
【问题描述】:

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

我正在使用 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));
        }
    }
}

MainView 包含 BusyIndi​​cator:

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

如果我在 MainViewModel 中设置 IsBusy = true,则会显示 BusyIndi​​cator。

如果我尝试从其他 ViewModel 设置 IsBusy = true,则不会显示 BusyIndi​​cator。

请注意,我不能在我的项目中使用 MVVMLight 之类的第 3 方库来使用他们的 Messenger 在 ViewModel 之间进行通信。

主视图:

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

ViewModel1:

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

【问题讨论】:

  • 仅供参考 MVVMLight 是开源的,您可以轻松地仅提取 Messenger 实现并丢弃其余实现 - 将源代码直接放在您的解决方案中,因此没有第三方库。
  • @AdamHouldsworth 好吧,由于某种原因,当我尝试使用 MVVMLight 中的 WeakReference 类时,我得到了 SecurtyException。我也尝试了调解器模式,但遇到了 WeakReference SecurityException 的问题。
  • @GazTheDestroyer 其他四个视图不包含对 MainView 的引用。
  • 那么 4 个 ViewModel 是如何应用于 4 个视图的呢?您是每次都将 MainView 的 DataContext 设置为不同的 ViewModel,还是 Views 完全分开而 MainView 看不到它们的 ViewModel?
  • @GazTheDestroyer 每个 View 都有对应的 ViewModel 作为 DataContext。 MainViewModel 引用了所有其他 ViewModel。但是,所有 ViewModel 都具有来自 BaseViewModel 的 IsBusy 属性。

标签: c# .net wpf mvvm wpftoolkit


【解决方案1】:
   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
   }
}

对所有视图模型重复订阅。

当您不再需要事件时,不要忘记取消订阅,以避免内存泄漏。

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

【讨论】:

  • 我绑定到 BaseViewModel 属性,该属性在所有 ViewModel 中都可见。如果我更改 IsBusy 属性,是否所有视图都会收到通知?
  • 不,绑定不是魔法。您有 4 个实例。 MainWindowViewModel、ViewModel1 等,它们每个都有它自己的 IsBusy 属性。当你设置ViewModel1.IsBusy = true时,其他IsBusy仍然是false。
  • 当您在 xaml 中设置 bindind 时,您连接了 MainWindowViewModel.IsBusy 属性并且它可以工作。但是您的视图无法检测到其他 IsBusy 属性。所以,你必须手动通知视图。
猜你喜欢
  • 1970-01-01
  • 2018-07-03
  • 2011-03-27
  • 1970-01-01
  • 2011-08-17
  • 2011-04-02
  • 2012-11-28
  • 2013-05-19
  • 2011-10-06
相关资源
最近更新 更多