2010-12-15 96 views
1

應用程序在prism/mvvm/mef中,並使用按類似StockTraderRI的屬性加載。prism:如何將shell.xaml中的某些內容綁定到區域內容變量?

我的shell窗口包含一個StatusBar的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沒有靜態資源。

任何人都可以指向我的方式來綁定Text屬性的一些屬性UserControl加載到MainRegion?

回答

2

我不認爲你將能夠找到一個乾淨的方式直接綁定到一個區域中的對象的屬性。你可以做到這一點的一種方法是讓指定區域中的所有視圖都從一個通用接口繼承,這樣它們都實現相同的屬性(比如SystemName)。您可能能夠綁定到包含該屬性的路徑,並使用ValueConverter將類型從System.Object更改爲接口類型。

我遇到的問題是,它限制了您可以放入該區域的內容,並且似乎將shell與其中顯示的類型耦合得比我個人更喜歡的類型。我會建議一個不同的路由:因爲你的狀態欄是你的shell的一部分,爲狀態欄綁定到你的屬性的shell有一個ViewModel,並且使用一個事件來跟蹤狀態值更改的時間。這樣做的一些好處:

  1. 您的事件可以發送任何具有您的shell可綁定到的任何數量的屬性的對象。這使得狀態欄以外的其他功能也可以使用它。
  2. 不與shell中各種對象交互的視圖不必傳輸事件。這使得在該區域中顯示的較大組件的子視圖不與殼體產生不利的相互作用,或者實現它們不需要的任何接口
  3. 它是Prism框架中定義良好的機制,因此是預期的方式以分發信息

請注意,您可以明確地定義事件是任何你需要的 - 我只是把一個參數的類型對象,但你可能希望這是更具體到您的整體需求。

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

現在,您所有的觀點都必須實施IActiveAware,並在活動成功時提出事件。或者,你可以讓View的ViewModel執行此操作(這可能會更好,但需要一些額外的溝通,關於這一點,有一些解釋here)。

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