2016-04-03 79 views
0

我目前正在與Prism 6 WPF應用程序工作...我有ShellViewModel,ViewAViewModel和ViewBViewModel。棱鏡6獲取ShellViewModel上下文內其他視圖模型

在Shell.xaml中,我定義了「mainRegion」。當應用程序啓動時,默認情況下在該區域顯示ViewA。

現在,當我從ViewA到VIEWB,在這一點(內部ViewBViewModel),我需要有ShellViewModel的上下文。

任何建議,以實現這一目標?

+0

爲什麼你需要ShellViewModel?你能提供更多的信息嗎? – toumir

+0

我的主屏幕(Shell.xaml)由兩個部分組成 (我)碳帶標籤(顯示菜單) (二)大區經理通過棱鏡 因此,根據功能區選項卡上單擊,區域管理器將顯示appropiate提供(i)ViewA - >顯示列表 (ii。)ViewB - >顯示錶格 假設我有兩個視圖 (i)ViewA→顯示列表 用戶可以通過編輯按鈕從ViewA到ViewB ...所以我需要顯示相應的選項卡相應地... 所以將在我的ViewBViewModel中請求ShellContext,以便我可以相應地設置選項卡的「IsSelected」屬性 – user1641519

回答

0

完整的源代碼!

ViewA.xaml

<UserControl x:Class="ModuleA.Views.ViewA" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"> <Grid> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" > <TextBlock Text="{Binding Title}" FontSize="38" /> <Button Command="{Binding UpdateCommand}" Width="100">Update</Button> </StackPanel> </Grid> </UserControl>

ViewA.xaml.cs

using ModuleA.RibbonTabs; 
using PrismDemo.Core; 
using System.Windows.Controls; 
namespace ModuleA.Views 
{ 
    [RibbonTab(typeof(ViewATab))] 
    public partial class ViewA : UserControl, ISupportDataContext 
    { 
    public ViewA() 
    { 
     InitializeComponent(); 
    } 
    } 
} 

ViewB.xaml

<UserControl x:Class="ModuleA.Views.ViewB" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"> <Grid> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" > <TextBlock Text="{Binding Title}" FontSize="38" /> <Button Command="{Binding UpdateCommand}" Width="100">Update</Button> </StackPanel> </Grid> </UserControl>

ViewB.xaml.cs

using ModuleA.RibbonTabs; 
using PrismDemo.Core; 
using System.Windows.Controls; 
namespace ModuleA.Views 
{ 
[RibbonTab(typeof(ViewBTab))] 
//the main view can inject any number of tab 
//uncomment the following lines and test 
//I added the same tab just for demo purposes 
//[RibbonTab(typeof(ViewBTab))] 
//[RibbonTab(typeof(ViewBTab))] 
//[RibbonTab(typeof(ViewBTab))] 
public partial class ViewB : UserControl, ISupportDataContext 
{ 
    public ViewB() 
    { 
     InitializeComponent(); 
    } 
} 
} 

ModuleAModule.cs

using Microsoft.Practices.Unity; 
using ModuleA.Views; 
using Prism.Modularity; 
using Prism.Unity; 

namespace ModuleA 
{ 
    public class ModuleAModule : IModule 
    { 
     IUnityContainer _container; 

     public ModuleAModule(IUnityContainer container) 
     { 
      _container = container; 
     } 

     public void Initialize() 
     { 
      //register for nav 
      _container.RegisterTypeForNavigation<ViewA>(); 
      _container.RegisterTypeForNavigation<ViewB>(); 
     } 
    } 
} 

RibbonTabAttribute.cs

using System; 

namespace PrismDemo.Core 
{ 
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] 
    public class RibbonTabAttribute : Attribute 
    { 
     public Type Type { get; private set; } 

     public RibbonTabAttribute(Type ribbonTabType) 
     { 
      Type = ribbonTabType; 
     } 
    } 
} 

個ISupportDataContext.cs

namespace PrismDemo.Core 
{ 
    public interface ISupportDataContext 
    { 
     object DataContext { get; set; } 
    } 
} 

bootstrapper.cs

using Prism.Unity; 
using PrismDemo.Views; 
using System.Windows; 
using Microsoft.Practices.Unity; 
using Prism.Modularity; 
using ModuleA; 
using Prism.Regions; 
using PrismDemo.Prism; 
using System.Windows.Controls.Ribbon; 

namespace PrismDemo 
{ 
    class Bootstrapper : UnityBootstrapper 
    { 
     protected override DependencyObject CreateShell() 
    { 
     return Container.Resolve<Shell>(); 
    } 

    protected override void InitializeShell() 
    { 
     Application.Current.MainWindow.Show(); 
    } 

    protected override void ConfigureModuleCatalog() 
    { 
     var catalog = (ModuleCatalog)ModuleCatalog; 
     catalog.AddModule(typeof(ModuleAModule)); 
    } 

    protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors() 
    { 
     var behaviors = base.ConfigureDefaultRegionBehaviors(); 
     behaviors.AddIfMissing(RibbonRegionBehavior.BehaviorKey, typeof(RibbonRegionBehavior)); 
     return behaviors; 
    } 
    } 
} 

的App.xaml

<Application x:Class="PrismDemo.App" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="clr-namespace:PrismDemo"> 
<Application.Resources> 
</Application.Resources> 
</Application> 

App.xaml.cs

using System.Windows; 
namespace PrismDemo 
{ 
    public partial class App : Application 
    { 
     protected override void OnStartup(StartupEventArgs e) 
     { 
      base.OnStartup(e); 

      var bs = new Bootstrapper(); 
      bs.Run(); 
     } 
    } 
} 

Shell.xaml

<Window x:Class="PrismDemo.Views.Shell" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:prism="http://prismlibrary.com/" 
prism:ViewModelLocator.AutoWireViewModel="True" 
Title="Shell" Height="720" Width="1280"> 
<Grid> 
<Grid.RowDefinitions> 
    <RowDefinition Height="auto"></RowDefinition> 
    <RowDefinition Height="*"></RowDefinition> 
</Grid.RowDefinitions> 
<Ribbon Grid.Row="0" prism:RegionManager.RegionName="RibbonTabRegion"/> 
<DockPanel LastChildFill="True" Grid.Row="1"> 
    <StackPanel> 
     <Button Content="Navigate ViewA" Command="{Binding NavigateCommand}" CommandParameter="ViewA" /> 
     <Button Content="Navigate ViewB" Command="{Binding NavigateCommand}" CommandParameter="ViewB" /> 
    </StackPanel> 
    <ContentControl prism:RegionManager.RegionName="ContentRegion" Margin="1,3,3,3" /> 
</DockPanel> 
</Grid> 
</Window> 

Shell.xaml.cs

namespace PrismDemo.Views 
{ 
    public partial class Shell 
    { 
     public Shell() 
     { 
      InitializeComponent(); 
     } 
    } 
} 

ShellViewModel。CS

using Prism.Commands; 
using Prism.Mvvm; 
using Prism.Regions; 

namespace PrismDemo.ViewModels 
{ 
public class ShellViewModel : BindableBase 
{ 
    IRegionManager _regionManager; 

    public DelegateCommand<string> NavigateCommand { get; set; } 

    public ShellViewModel(IRegionManager regionManager) 
    { 
     _regionManager = regionManager; 

     NavigateCommand = new DelegateCommand<string>(Navigate); 
    } 

    void Navigate(string navigationPath) 
    { 
     _regionManager.RequestNavigate("ContentRegion", navigationPath); 
    } 
} 
} 

RibbonRegionBehavior.cs

using Prism.Regions; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Collections.Specialized; 
using PrismDemo.Core; 
using System.Windows.Controls.Ribbon; 

namespace PrismDemo.Prism 
{ 
public class RibbonRegionBehavior : RegionBehavior 
{ 
    public const string BehaviorKey = "RibbonRegionBehavior"; 

    public const string RibbonTabRegionName = "RibbonTabRegion"; 

    protected override void OnAttach() 
    { 
     if (Region.Name == "ContentRegion") 
      Region.ActiveViews.CollectionChanged += ActiveViews_CollectionChanged; 
    } 

    private void ActiveViews_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if (e.Action == NotifyCollectionChangedAction.Add) 
     { 
      var tabList = new List<RibbonTab>(); 

      foreach (var newView in e.NewItems) 
      { 
       foreach (var atr in GetCustomAttributes<RibbonTabAttribute>(newView.GetType())) 
       { 
        var ribbonTabItem = Activator.CreateInstance(atr.Type) as RibbonTab; 

        if (ribbonTabItem is ISupportDataContext && newView is ISupportDataContext) 
         ((ISupportDataContext)ribbonTabItem).DataContext = ((ISupportDataContext)newView).DataContext; 

        tabList.Add(ribbonTabItem); 
       } 

       tabList.ForEach(x => Region.RegionManager.Regions[RibbonTabRegionName].Add(x)); 
      } 
     } 
     else if (e.Action == NotifyCollectionChangedAction.Remove) 
     { 
      var views = Region.RegionManager.Regions[RibbonTabRegionName].Views.ToList(); 
      views.ForEach(x => Region.RegionManager.Regions[RibbonTabRegionName].Remove(x)); 
     } 
    } 

    private static IEnumerable<T> GetCustomAttributes<T>(Type type) 
    { 
     return type.GetCustomAttributes(typeof(T), true).OfType<T>(); 
    } 
} 
} 

,這是演示程序的結構: Structure of the demo app

該溶液由Brian拉古納斯(棱鏡所有者)中提供他的Pluralsight課程(棱鏡問題&解決方案:加載從屬視圖),** **還有另一個解決方案由Brian,https://www.youtube.com/watch?v=xH6OgCxdXQc(再次)提供了這個問題,但我認爲第一個解決方案是最好的,最簡單的

在內容區域注入可注入任何數目的標籤看,看到評論中ViewB。 xaml.cs

+0

感謝您的評論! 你能在壓縮文件中分享上面的工作代碼嗎?因爲我沒有多個視線帳戶和上面的代碼給出一些錯誤。 – user1641519

+0

該解決方案完美地工作,這是下載演示項目的鏈接:https://onedrive.live.com/redir?resid=576726C17319C174!1229&authkey=!AE9MO4QC77LR7jM&ithint=file%2czip – toumir

+0

偉人:)非常感謝! 。我會檢查解決方案。 – user1641519