Description
When a view is injected into a region, trigger the load of other views in other regions and pass them the same DataContext.
Region behavior and Attribute
DependentViewAttribute.cs
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class DependentViewAttribute : Attribute
{
public Type Type { get; }
public string TargetRegionName { get; }
public DependentViewAttribute(Type viewType, string targetRegionName)
{
Type = viewType;
TargetRegionName = targetRegionName;
}
}
|
DependentViewRegionBehavior.cs
|
public class DependentViewRegionBehavior : RegionBehavior
{
private readonly Dictionary<object, List<DependentViewInfo>> _dependentViewCache = new Dictionary<object, List<DependentViewInfo>>();
protected override void OnAttach()
{
Region.ActiveViews.CollectionChanged += ActiveViewsOnCollectionChanged;
}
private void ActiveViewsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var view in e.NewItems)
{
if (!_dependentViewCache.TryGetValue(view, out var viewInfoList))
{
viewInfoList = new List<DependentViewInfo>();
foreach (var attribute in GetCustomAttribute<DependentViewAttribute>(view.GetType()))
{
var viewInfo = CreateDependentView(attribute);
if (viewInfo.View is FrameworkElement viewToInject &&
view is FrameworkElement viewTrigger)
{
viewToInject.DataContext = viewTrigger.DataContext;
}
viewInfoList.Add(viewInfo);
}
if (!_dependentViewCache.ContainsKey(view))
{
_dependentViewCache.Add(view, viewInfoList);
}
}
viewInfoList.ForEach(x => Region.RegionManager.Regions[x.TargetRegionName].Add(x.View));
}
}
if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (var view in e.OldItems)
{
if (_dependentViewCache.TryGetValue(view, out var viewInfoList))
{
viewInfoList.ForEach(x => Region.RegionManager.Regions[x.TargetRegionName].Remove(x.View));
}
}
}
}
private DependentViewInfo CreateDependentView(DependentViewAttribute attribute)
{
return new DependentViewInfo
{
View = attribute.Type != null ? Activator.CreateInstance(attribute.Type) : null,
TargetRegionName = attribute.TargetRegionName
};
}
private static IEnumerable<T> GetCustomAttribute<T>(Type type) => type.GetCustomAttributes(typeof(T), true).OfType<T>();
}
internal class DependentViewInfo
{
public object View { get; set; }
public string TargetRegionName { get; set; }
}
|
App.xaml.cs
|
protected override void ConfigureDefaultRegionBehaviors(IRegionBehaviorFactory regionBehaviors)
{
base.ConfigureDefaultRegionBehaviors(regionBehaviors);
regionBehaviors.AddIfMissing(nameof(DependentViewRegionBehavior), typeof(DependentViewRegionBehavior));
}
|
Views and ViewModels
MainWindow.xaml
|
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Menu prism:RegionManager.RegionName="MenuRegion" />
<ContentControl Grid.Row="1"
prism:RegionManager.RegionName="StepRegion" />
</Grid>
|
StepOneView.xaml.cs
|
[DependentView(typeof(NextMenuItemView), "MenuRegion")]
public partial class StepOneView
{ }
|
StepOneViewModel.cs
|
public class StepOneViewModel : BindableBase
{
private readonly IRegionManager _regionManager;
public ICommand GoToNextStepCommand { get; }
public StepOneViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
GoToNextStepCommand = new DelegateCommand(GoToNextStep);
}
private void GoToNextStep()
{
_regionManager.RequestNavigate("StepRegion", "StepTwoView");
}
}
|
StepTwoView.xaml.cs
|
[DependentView(typeof(PreviousMenuItemView), "MenuRegion")]
[DependentView(typeof(NextMenuItemView), "MenuRegion")]
public partial class StepTwoView
{ }
|
StepTwoViewModel.cs
|
public class StepTwoViewModel : BindableBase
{
private readonly IRegionManager _regionManager;
public ICommand GoToPreviousStepCommand { get; }
public ICommand GoToNextStepCommand { get; }
public StepTwoViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
GoToPreviousStepCommand = new DelegateCommand(GoToPreviousStep);
GoToNextStepCommand = new DelegateCommand(GoToNextStep);
}
private void GoToPreviousStep()
{
_regionManager.RequestNavigate("StepRegion", "StepOneView");
}
private void GoToNextStep()
{
_regionManager.RequestNavigate("StepRegion", "StepThreeView");
}
}
|
StepThreeView.xaml.cs
|
[DependentView(typeof(PreviousMenuItemView), "MenuRegion")]
public partial class StepThreeView
{ }
|
StepThreeViewModel.cs
|
public class StepThreeViewModel : BindableBase
{
private readonly IRegionManager _regionManager;
public ICommand GoToPreviousStepCommand { get; }
public StepThreeViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
GoToPreviousStepCommand = new DelegateCommand(GoToPreviousStep);
}
private void GoToPreviousStep()
{
_regionManager.RequestNavigate("StepRegion", "StepTwoView");
}
}
|