首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >支持订购的自定义StackPanel棱镜RegionAdapter

支持订购的自定义StackPanel棱镜RegionAdapter
EN

Stack Overflow用户
提问于 2013-07-14 17:14:18
回答 3查看 199关注 0票数 2

我有以下针对StackPanel的RegionAdapter实现,但我需要对与区域关联的项进行严格排序。有谁可以帮助我吗?

我希望注册到区域的视图能够控制那里的位置,也许是某种索引号

代码语言:javascript
复制
    protected override void Adapt(IRegion region, StackPanel regionTarget)
    {
        region.Views.CollectionChanged += (sender, e) =>
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (FrameworkElement element in e.NewItems)
                    {
                        regionTarget.Children.Add(element);
                    }

                    break;

                case NotifyCollectionChangedAction.Remove:
                    foreach (UIElement elementLoopVariable in e.OldItems)
                    {
                        var element = elementLoopVariable;
                        if (regionTarget.Children.Contains(element))
                        {
                            regionTarget.Children.Remove(element);
                        }
                    }

                    break;
            }
        };
    }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-07-14 17:57:18

如何处理这个问题在很大程度上取决于排序是指(a)视图的类型还是(b)视图的实例。例如,如果您只想指定类型为ViewA的视图应该位于类型为ViewB的视图之上,则可以使用前者。如果您想指定如何对同一视图类型的多个具体实例进行排序,则可以使用后一种方法。

A.按类型排序

On选项是实现一个自定义属性,类似于OrderIndexAttribute,它公开一个整数属性:

代码语言:javascript
复制
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public OrderIndexAttribute : Attribute
{
    public int Index { get; }

    public OrderIndexAttribute(int index)
    {
        Index = index;
    }
}

使用该属性标记视图类:

代码语言:javascript
复制
[OrderIndex(2)]
public ViewA : UserControl
{...}

在将视图添加到地域时获取类型的属性:

代码语言:javascript
复制
case NotifyCollectionChangedAction.Add:
    foreach (FrameworkElement element in e.NewItems)
    {
        // Get index for view
        var viewType = element.GetType();
        var viewIndex= viewType.GetCustomAttribute<OrderIndexAttribute>().Index;
        // This method needs to iterate through the views in the region and determine
        // where a view with the specified index needs to be inserted
        var insertionIndex = GetInsertionIndex(viewIndex);
        regionTarget.Children.Insert(insertionIndex, element);
    }
    break;

B.对实例进行排序

让你的视图实现一个接口:

代码语言:javascript
复制
public interface ISortedView 
{
   int Index { get; }
}

在将视图添加到区域时,尝试将插入的视图转换到界面,读取索引,然后执行上述操作:

代码语言:javascript
复制
case NotifyCollectionChangedAction.Add:
    foreach (FrameworkElement element in e.NewItems)
    {
        // Get index for view
        var sortedView = element as ISortedView;
        if (sortedView != null)
        {
            var viewIndex = sortedView.Index;
            // This method needs to iterate through the views in the region and determine
            // where a view with the specified index needs to be inserted
            var insertionIndex = GetInsertionIndex(viewIndex);
            regionTarget.Children.Insert(insertionIndex, sortedView);
        }
        else
        { // Add at the end of the StackPanel or reject adding the view to the region }
    }
票数 2
EN

Stack Overflow用户

发布于 2020-11-14 07:12:10

我发现Marc的"A。Sort type wise“案例对我的情况非常有帮助。我需要使用OrderIndexAttribute将视图排序到区域中,并且如果视图实际上没有OrderIndexAttribute,仍然可以添加视图。

正如您将在下面看到的,我通过跟踪列表中的视图索引实现了这一点。没有该属性的视图的插入索引默认为零,以便它排序到StackPanel的前面(或顶部)。

这篇原创文章相当古老,但也许有人会像我一样偶然发现它,并会发现我的贡献是有帮助的。重构建议是受欢迎的。:-)

代码语言:javascript
复制
public class StackPanelRegionAdapter : RegionAdapterBase<StackPanel>
{
    private readonly List<int> _indexList;

    public StackPanelRegionAdapter(IRegionBehaviorFactory behaviorFactory)
        : base(behaviorFactory)
    {
        _indexList = new List<int>();
    }

    protected override void Adapt(IRegion region, StackPanel regionTarget)
    {
        
        region.Views.CollectionChanged += (sender, e) =>
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (FrameworkElement element in e.NewItems)
                    {
                        var viewType = element.GetType();

                        // Get the custom attributes for this view, if any
                        var customAttributes = viewType.GetCustomAttributes(false);

                        var viewIndex = 0;  // Default the viewIndex to zero

                        // Determine if the view has the OrderIndexAttribute.
                        // If it does have the OrderIndexAttribute, get its sort index.
                        if (HasThisAttribute(customAttributes))
                        {
                            viewIndex= viewType.GetCustomAttribute<OrderIndexAttribute>().Index;
                        }
                        
                        // Get the insertion index
                        var insertionIndex = GetInsertionIndex(viewIndex);

                        regionTarget.Children.Insert(insertionIndex, element);
                    }
                    break;

                case NotifyCollectionChangedAction.Remove:
                    foreach (UIElement elementLoopVariable in e.OldItems)
                    {
                        var element = elementLoopVariable;
                        if (regionTarget.Children.Contains(element))
                        {
                            regionTarget.Children.Remove(element);
                        }
                    }
                    break;
            }
        };
    }

    private static bool HasThisAttribute(IReadOnlyList<object> customAttributes)
    {
        // Determine if the view has the OrderIndexAttribute
        if (customAttributes.Count == 0) return false;
        for (var i = 0; i < customAttributes.Count; i++)
        {
            var name = customAttributes[i].GetType().Name;
            if (name == "OrderIndexAttribute") return true;
        }

        return false;
    }

    private int GetInsertionIndex(in int viewIndex)
    {
        // Add the viewIndex to the index list if not already there
        if (_indexList.Contains(viewIndex) == false)
        {
            _indexList.Add(viewIndex);
            _indexList.Sort();
        }

        // Return the list index of the viewIndex
        for (var i = 0; i < _indexList.Count; i++)
        {
            if (_indexList[i].Equals(viewIndex))
            {
                return i;
            }
        }

        return 0;
    }

    protected override IRegion CreateRegion()
    {
        return new AllActiveRegion();
    }
}
票数 0
EN

Stack Overflow用户

发布于 2021-08-24 00:17:59

Marc和R.Evans的回答帮助我创建了自己的更通用的RegionAdapter,并进行了以下改进:

  • 使用ViewSortHint与Prism 6
  • Prism 7/ .Net 5 Prism类兼容,以便在多个适配器中使用
  • less code

自适应方法:

代码语言:javascript
复制
    protected override void Adapt(IRegion region, StackPanel regionTarget)
    {
        region.Views.CollectionChanged += (s, e) =>
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
                foreach (FrameworkElement item in e.NewItems)
                {
                    regionTarget.Children.Insert(regionTarget.Children.GetInsertionIndex(item), item);
                }
            else if (e.Action == NotifyCollectionChangedAction.Remove)
                foreach (UIElement item in e.OldItems)
                {
                    if (regionTarget.Children.Contains(item))
                    {
                        regionTarget.Children.Remove(item);
                    }
                }
        };
    }

帮助器/扩展:

代码语言:javascript
复制
internal static int GetInsertionIndex(this IList items, in object newItem)
    {
        // Return the list index of the viewIndex
        foreach (object item in items)
        {
            var currentIndex = item.GetType().GetCustomAttribute<ViewSortHintAttribute>()?.Hint ?? "0";
            var intendedIndex = newItem.GetType().GetCustomAttribute<ViewSortHintAttribute>()?.Hint ?? "0";

            if (currentIndex.CompareTo(intendedIndex) >= 0)
                return items.IndexOf(item);
        }

        // if no greater index is found, insert the item at the end
        return items.Count;
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17638053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档