« Prism loading dependent views » : différence entre les versions

De Banane Atomic
Aller à la navigationAller à la recherche
(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… »)
 
Ligne 4 : Ligne 4 :


= Region behavior and Attribute =
= Region behavior and Attribute =
<filebox fn='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;
    }
}
</filebox>
<filebox fn='DependentViewRegionBehavior.cs'>
<filebox fn='DependentViewRegionBehavior.cs'>
public class DependentViewRegionBehavior : RegionBehavior
public class DependentViewRegionBehavior : RegionBehavior

Version du 27 octobre 2021 à 15:25

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