Wpf XAML中的VisualCollection和ContentPropertyAttribute

Wpf XAML中的VisualCollection和ContentPropertyAttribute,wpf,xaml,Wpf,Xaml,我想写一个自定义的框架元素来承载视觉效果。我的第一次尝试是创建一个ContainerVisual实例,并为ContainerVisual.Children编写一个包装器属性,然后将其设置为ContentProperty,这样我就可以通过XAML查看和显示。但VisualCollection只实现ICollection,而不实现IList或任何支持的接口,VisualCollection是selead,因此我无法单独实现IList 我怎样才能承载视觉效果并让它们使用XAML以声明方式添加?好的,很

我想写一个自定义的框架元素来承载视觉效果。我的第一次尝试是创建一个ContainerVisual实例,并为ContainerVisual.Children编写一个包装器属性,然后将其设置为ContentProperty,这样我就可以通过XAML查看和显示。但VisualCollection只实现ICollection,而不实现IList或任何支持的接口,VisualCollection是selead,因此我无法单独实现IList


我怎样才能承载视觉效果并让它们使用XAML以声明方式添加?

好的,很久以前,但这是我以前找到的解决方案

收藏: 注意黑客的评论

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Collections.ObjectModel;
using WPF.Controls.Primitives;

namespace WPF.Controls.Core
{
    public class PrimitiveCollection : ObservableCollection<Primitive>
    {
        protected PrimitiveContainerVisual _owner;

        public PrimitiveCollection(PrimitiveContainerVisual owner)
            : base()
        {
            if (owner == null)
                throw new ArgumentNullException("owner");

            _owner = owner;
        }

        protected override void ClearItems()
        {
            foreach (var item in this)
            {
                item.IsDirtyChanged -= new IsDirtyChangedHandler(item_IsDirtyChanged);
                _owner.InternalRemoveVisualChild(item);
            }

            base.ClearItems();
        }

        protected override void InsertItem(int index, Primitive item)
        {
            if (item != null && item.Parent != null)
                throw new ArgumentNullException("Visual has parent");

            item.IsDirtyChanged += new IsDirtyChangedHandler(item_IsDirtyChanged);
            _owner.InternalAddVisualChild(item);

            base.InsertItem(index, item);
        }

        protected override void RemoveItem(int index)
        {
            Primitive item = this[index];

            item.IsDirtyChanged -= new IsDirtyChangedHandler(item_IsDirtyChanged);
            _owner.InternalRemoveVisualChild(item);
            base.RemoveItem(index);
        }

        protected override void OnPropertyChanged(System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
        }

        void item_IsDirtyChanged(object sender, PrimitiveChangedEventArgs e)
        {
            if(e.IsDirty)
                _owner.RequestRedraw();
        }
    }
}

你能解释一下吗?请问一个具体的问题。这个问题很老了。最好创建一个新的,并在评论中发布链接。然后我会看看我是否能帮上忙:)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using WPF.Controls.Primitives;
using System.Windows;
using System.Reflection;

namespace WPF.Controls.Core
{
    public class PrimitiveContainerVisual : Visual
    {
        private PrimitiveCollection _primitives;
        private PropertyInfo _contentBoundsPropInfo;
        private PropertyInfo _descendantBoundsPropInfo;

        public PrimitiveCollection Children
        {
            get { return _primitives; }
            set { _primitives = value; }
        }

        public Rect ContentBounds
        {
            // HACK access internal property of Visual
            get { return (Rect)_contentBoundsPropInfo.GetValue(this, null); }
        }

        public Rect DescendantBounds
        {
            // HACK access internal property of Visual
            get { return (Rect)_descendantBoundsPropInfo.GetValue(this, null); }
        }

        public PrimitiveContainerVisual()
        {
            _primitives = new PrimitiveCollection(this);
            Type thisType = this.GetType();
            BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
            _contentBoundsPropInfo = thisType.GetProperty("VisualContentBounds", flags);
            _descendantBoundsPropInfo = thisType.GetProperty("VisualDescendantBounds", flags);
        }

        internal void InternalAddVisualChild(Primitive prim)
        {
            this.AddVisualChild(prim);
        }

        internal void InternalRemoveVisualChild(Primitive prim)
        {
            this.RemoveVisualChild(prim);
        }

        public bool RequestRedraw()
        {
            UIElement uiParent = VisualParent as UIElement;

            if (uiParent != null)
            {
                uiParent.InvalidateVisual();
                return true;
            }
            else
                return false;
        }
    }
}