2016-04-03 4 views
0

Ich arbeite derzeit an WPF App mit Prism 6 ... Ich habe ShellViewModel, ViewAViewModel und ViewBViewModel.Prism 6 bekomme ShellViewModel Kontext in anderen viewModel

In Shell.xaml habe ich "MainRegion" definiert. Wenn App gestartet wird, zeige ich ViewA standardmäßig in dieser Region an.

Jetzt, wenn ich von ViewA zu VIEWB gehe, an dieser Stelle (Inside ViewBViewModel), muss ich Kontext von ShellViewModel haben.

Irgendwelche Vorschläge, um dies zu erreichen?

+0

Warum benötigen Sie das ShellViewModel? Kannst du mehr Informationen geben? – toumir

+0

Mein Hauptbildschirm (Shell.xaml) besteht aus zwei Teilen (i.) Ribbon Tab (Menü anzuzeigen) (ii.) Region-Manager von Prisma vorgesehen also je nach Band Registerkarte geklickt hat, werden Region-Manager sachgemäßen zeigen Views (Usercontrols ...) Angenommen, ich hv zwei Ansichten (i) ViewA -> Zeige Liste (ii.) ViewB -> Zeige Formular Benutzer kann von ViewA zu ViewB gehen durch Bearbeiten Schaltfläche ... Also muss ich den entsprechenden Reiter entsprechend ausgewählt haben ... Also werde ich ShellContext in meinem ViewBViewModel anfordern, damit ich die "IsSelected" -Eigenschaft des Tabs entsprechend setzen kann – user1641519

Antwort

0

der vollständige Quellcode!

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

und dies ist die Struktur der Demo-App: Structure of the demo app

diese Lösung von Brian Lagunas (Prisma owner) versehen wurde sein Pluralsight Kurs (Prism Probleme & Lösungen: Laden Abhängige Ansichten), ** ** Es gibt eine andere Lösung für dieses Problem zur Verfügung gestellt (wieder) durch brian, https://www.youtube.com/watch?v=xH6OgCxdXQc, aber ich denke, die erste Lösung die beste ist und die einfachste

der Blick in den Inhalt Bereich injiziert kann eine beliebige Anzahl von Tabs einspritzt, siehe Kommentar in ViewB. xaml.cs

+0

Danke für deinen Kommentar! Sind Sie in der Lage, über Arbeitscode in gezippter Datei zu teilen, wie ich Plural Sichtkonto und über Code nicht habe, der etwas Fehler gibt. – user1641519

+0

die Lösung funktioniert perfekt, und das ist der Link zum Download des Demoprojekts: https://onedrive.live.com/redir?resid=576726C17319C174!1229&authkey=!AE9MO4QC77LR7jM&hittinfofile%2czip – toumir

+0

Großer Mann :) Vielen Dank! . Ich werde die Lösung prüfen. – user1641519