Prism loading dependent views

De Banane Atomic
Version datée du 27 octobre 2021 à 15:24 par Nicolas (discussion | contributions) (Page créée avec « Category:WPF = 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 beha… »)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigationAller à la recherche

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

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