Mvvm prism:如何将shell.xaml中的内容绑定到区域内容变量?

Mvvm prism:如何将shell.xaml中的内容绑定到区域内容变量?,mvvm,binding,prism,Mvvm,Binding,Prism,应用程序位于prism/mvvm/mef中,并使用StockTraderRI等属性加载 My shell窗口包含状态栏的DockPanel,它是shell的全局,而不是每个区域的局部 看起来像这样: <DockPanel> <StatusBar DockPanel.Dock="Bottom"> <StatusBarItem> <TextBlock Text="{Binding Source={x:Static bcl:Config

应用程序位于prism/mvvm/mef中,并使用StockTraderRI等属性加载

My shell窗口包含状态栏的DockPanel,它是shell的全局,而不是每个区域的局部

看起来像这样:

<DockPanel>
  <StatusBar DockPanel.Dock="Bottom">
    <StatusBarItem>
      <TextBlock Text="{Binding Source={x:Static bcl:Configuration.Global}, Path=LoggedOn.User}"/>
    </StatusBarItem>
    <StatusBarItem>
      <TextBlock Text="{Binding StateMessage}"/>
    </StatusBarItem>
  </StatusBar>
  <ContentControl x:Name="MainContent" cal:RegionManager.RegionName="MainRegion"/>
</DockPanel>

绑定到全局变量确实很有效。现在,我想将StatusBarItem中的StateMessage绑定到加载到MainRegion的任何控件中的属性StateMessage。
我的第一个猜测是使用如下内容:

<TextBlock Text="{Binding Path=DataContext.StateMessage,Source={StaticResource MainContent}}"/>

但这当然不起作用,因为MainContent不是静态资源


有人能告诉我一种将文本属性绑定到加载到MainRegion中的UserControl的某些属性的方法吗?

我认为您无法找到一种直接绑定到区域中对象的属性的干净方法。实现这一点的一种方法是让指定区域中的所有视图从公共接口继承,以便它们都实现相同的属性(例如,SystemName)。您可以绑定到包含该属性的路径,并使用ValueConverter将类型从System.Object更改为接口类型

我的问题是,它限制了您可以在区域中输入的内容,并且似乎将shell与其中显示的类型耦合起来,这超出了我个人的意愿。我建议采用另一种方法:因为状态栏是shell的一部分,所以为shell提供一个ViewModel,其中包含状态栏绑定到的属性,并使用事件跟踪状态值何时更改。这样做有几个好处:

  • 事件可以发送具有shell可以绑定的任意数量属性的任何对象。这让状态栏以外的东西也可以使用它
  • 不与shell中的各种对象交互的视图不必传输事件。这使得在区域中显示的较大组件的子视图不会与shell产生负面交互,也不会实现它们不需要的任何接口
  • 它是Prism框架中定义良好的机制,因此是分发信息的预期方式
  • 请注意,您显然可以将事件定义为您需要的任何类型-我只是输入了Object类型的参数,但您可能希望它更具体地满足您的总体需求

    // Use normal binding for Shell -> ShellViewModel
    public sealed ShellViewModel : INotifyPropertyChanged
    {
       private readonly IEventAggregator = eventAggregator;
    
       public ShellViewModel(IEventAggregator eventAggregator)
       {
          _eventAggregator = eventAggregator;
    
          _eventAggregator.GetEvent<MainRegionViewLoaded>.Subscribe(
             new Action<Object>(HandleMainRegionViewLoaded));
       }
    
       private String _statusName;
       public String StatusName
       {
          get { return _statusName; }
          set
          {
             if (_statusName != value)
             {
                _statusName = value;
                RaisePropertyChanged("StatusName"); // Not showing this...
             }
          }
       }
    
       private void HandleMainRegionViewLoaded(Object param)
       {
          // Not doing all the checking here, such as null, etc.
          var statusName = param as String;
          StatusName = statusName;
       }
    }
    
    //对Shell->ShellViewModel使用普通绑定
    公共密封ShellViewModel:INotifyPropertyChanged
    {
    私有只读IEventAggregator=eventAggregator;
    公共ShellViewModel(IEventAggregator事件聚合器)
    {
    _eventAggregator=eventAggregator;
    _eventAggregator.GetEvent.Subscribe(
    新操作(HandleMainRegionViewLoaded);
    }
    私有字符串_statusName;
    公共字符串状态名
    {
    获取{return\u statusName;}
    设置
    {
    如果(_statusName!=值)
    {
    _statusName=值;
    RaisePropertyChanged(“StatusName”);//不显示此。。。
    }
    }
    }
    私有void HandleMainRegionViewLoaded(对象参数)
    {
    //没有在这里执行所有检查,例如null等。
    var statusName=param作为字符串;
    StatusName=StatusName;
    }
    }
    
    现在,您的视图所要做的就是实现IActiveAware,并在激活时引发事件。或者,您可以让视图的ViewModel执行此操作(这可能更好,但需要一些额外的通信。对此有一些解释)

    public void主视图:用户控件,IActiveAware
    {
    私有只读ieventagegrator\u事件聚合器;
    公共主视图(IEventAggregator事件聚合器)
    {
    初始化组件();
    _eventAggregator=eventAggregator;
    }
    私人楼宇是活跃的;
    公共福利活动
    {
    获取{return\u isActive;}
    设置
    {
    如果(值)
    {
    _eventAggregator.GetEvent.Publish(新的MainRegionViewLoaded(“我的名字”);
    }
    _i活跃=价值;
    }
    }
    }
    
    public void MainView : UserControl, IActiveAware
    {
    
       private readonly IEventAggregator _eventAggregator;
    
       public MainView(IEventAggregator eventAggregator)
       {
          InitializeComponent();
    
          _eventAggregator = eventAggregator;
       }
    
       private bool _isActive;
       public bool IsActive
       {
          get { return _isActive; }
          set
          {
             if (value)
             {
                _eventAggregator.GetEvent<MainRegionViewLoaded>.Publish(new MainRegionViewLoaded("My Name"));
             }
             _isActive = value;
          }
       }
    }