Wpf 在ItemsControl中插入项

Wpf 在ItemsControl中插入项,wpf,xaml,silverlight,winrt-xaml,itemscontrol,Wpf,Xaml,Silverlight,Winrt Xaml,Itemscontrol,以下是要求 在我的代码> ITEMsStase(您可以使用 ListVIEW < /代码>,如果它有助于您考虑该场景)。我想将唯一的数据模板注入列表中的任意索引位置,而不是记录 例如,我可能希望将其插入第一个位置,索引0,或第三个位置,索引2,或者甚至可能有逻辑将其插入最后一个位置,索引count-1 我意识到,我需要子类ListView来实现这一点。也就是说,我可以很容易地创建SpecialItemTemplate、SpecialItemIndex DP属性来获得这些值 新增要求: 不需要特殊

以下是要求

在我的代码> ITEMsStase(您可以使用<代码> ListVIEW < /代码>,如果它有助于您考虑该场景)。我想将唯一的数据模板注入列表中的任意索引位置,而不是记录

例如,我可能希望将其插入第一个位置,索引0,或第三个位置,索引2,或者甚至可能有逻辑将其插入最后一个位置,索引count-1

我意识到,我需要子类ListView来实现这一点。也就是说,我可以很容易地创建SpecialItemTemplate、SpecialItemIndex DP属性来获得这些值

新增要求:

  • 不需要特殊类型的集合
  • 不需要操作现有数据
  • 允许ISITETSTVISIBLE也是可变的

  • (在WinRT中)如何完成这一壮举有什么想法吗?

    这里有一个解决方案,它基本上是一种
    行为
    ,带有
    模板
    属性,可以附加到任何
    项控件
    。我用虚拟化和非虚拟化面板测试了它,这两种情况都适用。如果你认为代码很复杂。。。好吧,我不能不同意,前一段时间写的,我记不起我为什么要这样写

    用法:

    <ListBox ItemsSource="{Binding Persons}">
    
        <Interactivity:Interaction.Behaviors>
            <AlternativeItemTemplate Index="42">
                <DataTemplate>
                    ...foo...
                </DataTemplate>
            </AlternativeItemTemplate>
        </Interactivity:Interaction.Behaviors>
    
        <ListBox.ItemTemplate>
            <DataTemplate>
                ...bar...
            </DataTemplate>
        </ListBox.ItemTemplate>
    
    </ListBox>
    
    
    ……福。。。
    …酒吧。。。
    
    课程包括:

    [ContentProperty( "ItemTemplate" )]
    public class AlternativeItemTemplate : ItemContainerDecorator
    {
        public DataTemplate ItemTemplate
        {
            get { return (DataTemplate) GetValue( ItemTemplateProperty ); }
            set { SetValue( ItemTemplateProperty, value ); }
        }
    
        public static readonly DependencyProperty ItemTemplateProperty =
            DependencyProperty.Register( "ItemTemplate", typeof( DataTemplate ), typeof( AlternativeItemTemplate ), new PropertyMetadata( null ) );
    
        public int Index
        {
            get { return (int) GetValue( IndexProperty ); }
            set { SetValue( IndexProperty, value ); }
        }
    
        public static readonly DependencyProperty IndexProperty =
            DependencyProperty.Register( "Index", typeof( int ), typeof( AlternativeItemTemplate ), new PropertyMetadata( -1 ) );
    
        protected override void OnContainersChanged()
        {
            if (!AssociatedObject.Items.Any() || Index < 0 || Index >= AssociatedObject.Items.Count)
            {
                ItemContentPresenter = null;
                ItemContentControl = null;
                m_overwrittenTemplate = null;
                return;
            }
    
            TryUpdateItem( ItemContainerGenerator.ContainerFromItem( AssociatedObject.Items[Index] ) );
        }
    
        private ContentPresenter ItemContentPresenter { get; set; }
        private ContentControl ItemContentControl { get; set; }
        private DataTemplate m_overwrittenTemplate;
    
        private void TryUpdateItem( DependencyObject itemContainer )
        {
            if (itemContainer == null)
            {
                ResetOverwrittenTemplate();
            }
    
            var containerAsPresenter = itemContainer as ContentPresenter;
            if (containerAsPresenter != null) UpdateItemContentPresenter( containerAsPresenter );
            else
            {
                var containerAsControl = itemContainer as ContentControl;
                if (containerAsControl != null) UpdateItemContentControl( containerAsControl );
            }
        }
    
        private void ResetOverwrittenTemplate()
        {
            if (ItemContentPresenter != null)
                ItemContentPresenter.ContentTemplate = m_overwrittenTemplate;
    
            if (ItemContentControl != null)
                ItemContentControl.ContentTemplate = m_overwrittenTemplate;
    
            ItemContentPresenter = null;
            ItemContentControl = null;
    
            m_overwrittenTemplate = null;
        }
    
        private void UpdateItemContentPresenter( ContentPresenter container )
        {
            if (ItemContentPresenter != null)
                ItemContentPresenter.ContentTemplate = m_overwrittenTemplate;
    
            ItemContentPresenter = container;
            m_overwrittenTemplate = ItemContentPresenter.ContentTemplate;
            ItemContentPresenter.ContentTemplate = ItemTemplate;
        }
    
        private void UpdateItemContentControl( ContentControl container )
        {
            if (ItemContentControl != null)
                ItemContentControl.ContentTemplate = m_overwrittenTemplate;
    
            ItemContentControl = container;
            m_overwrittenTemplate = ItemContentControl.ContentTemplate;
            ItemContentControl.ContentTemplate = ItemTemplate;
        }
    }
    
    public abstract class ItemContainerDecorator : Behavior<ItemsControl>
    {
        private Dictionary<object, DependencyObject> LastKnownContainers = new Dictionary<object, DependencyObject>();
    
        protected ItemContainerGenerator ItemContainerGenerator { get { return (AssociatedObject != null) ? AssociatedObject.ItemContainerGenerator : null; } }
    
        protected override void OnAttached()
        {
            base.OnAttached();
            ItemContainerGenerator.ItemsChanged += HandleItemsChangedInitially;
    
            if (!TryAddObservers())
            {
                AssociatedObject.Loaded += AddObserversOnLoaded;
            }
    
            AssociatedObject.Loaded += OnItemsControlLoaded;
            AssociatedObject.LayoutUpdated += OnItemsControlLayoutUpdated;
    
            CheckContainersChanged();
        }
    
        private void OnItemsControlLayoutUpdated(object sender, EventArgs eventArgs)
        {
            CheckContainersChanged();
        }
    
        private void OnItemsControlLoaded(object sender, RoutedEventArgs e)
        {
            CheckContainersChanged();
        }
    
        private void AddObserversOnLoaded( object sender, RoutedEventArgs e )
        {
            AssociatedObject.Loaded -= AddObserversOnLoaded;
            TryAddObservers();
        }
    
        private bool TryAddObservers()
        {
            const bool success = true;
            Panel itemsHost =
                AssociatedObject.GetVisualDescendants().OfType<Panel>().FirstOrDefault( panel => panel.IsItemsHost );
    
            if (itemsHost != null)
            {
                var virtualizingItemsHost = itemsHost as VirtualizingPanel;
                if (virtualizingItemsHost != null)
                {
                    virtualizingItemsHost.LayoutUpdated += OnVirtualizingItemsHostLayoutUpdated;
                    m_virtualizingItemsHost = virtualizingItemsHost;
                }
                return success;
            }
            return !success;
        }
    
        private VirtualizingPanel m_virtualizingItemsHost;
        private bool LayoutUpdatedOccurredFirst;
    
        private void OnVirtualizingItemsHostLayoutUpdated( object sender, EventArgs eventArgs )
        {
            LayoutUpdatedOccurredFirst = true;
            CheckContainersChanged();
        }
    
        protected override void OnDetaching()
        {
            ItemContainerGenerator.ItemsChanged -= HandleItemsChangedInitially;
            ItemContainerGenerator.ItemsChanged -= HandleItemsChanged;
    
            AssociatedObject.Loaded -= OnItemsControlLoaded;
            AssociatedObject.LayoutUpdated -= OnItemsControlLayoutUpdated;
    
            AssociatedObject.Loaded -= AddObserversOnLoaded;
            if (m_virtualizingItemsHost != null) m_virtualizingItemsHost.LayoutUpdated -= OnVirtualizingItemsHostLayoutUpdated;
            m_virtualizingItemsHost = null;
    
            base.OnDetaching();
        }
    
        private void HandleItemsChangedInitially( object sender, ItemsChangedEventArgs e )
        {
            ItemContainerGenerator.ItemsChanged -= HandleItemsChangedInitially;
    
            if (!LayoutUpdatedOccurredFirst)
            {
    
                //sometimes calling UpdateLayout throws an ArgumentException
                //don't know why so we just swallow it
                //it's not particularly important
                try
                {
                    AssociatedObject.UpdateLayout();
                }
                catch (ArgumentException) { }
            }
    
            ItemContainerGenerator.ItemsChanged += HandleItemsChanged;
            CheckContainersChanged();
        }
    
        private void HandleItemsChanged( object sender, ItemsChangedEventArgs e )
        {
            CheckContainersChanged();
        }
    
        private void CheckContainersChanged()
        {
            var newestContainers = new Dictionary<object, DependencyObject>();
            foreach (var item in AssociatedObject.Items)
            {
                newestContainers[item] = ItemContainerGenerator.ContainerFromItem( item );
            }
    
            if (!LastKnownContainers.SequenceEqual( newestContainers ))
            {
                LastKnownContainers = newestContainers;
                OnContainersChanged();
            }
        }
    
        protected abstract void OnContainersChanged();
    }
    
    [ContentProperty(“ItemTemplate”)]
    公共类AlternativeItemTemplate:ItemContainerDecorator
    {
    公共数据模板ItemTemplate
    {
    获取{return(DataTemplate)GetValue(ItemTemplateProperty);}
    set{SetValue(ItemTemplateProperty,value);}
    }
    公共静态只读DependencyProperty ItemTemplateProperty=
    DependencyProperty.Register(“ItemTemplate”、typeof(DataTemplate)、typeof(AlternativeItemTemplate)、new PropertyMetadata(null));
    公共整数索引
    {
    获取{return(int)GetValue(IndexProperty);}
    set{SetValue(IndexProperty,value);}
    }
    公共静态只读从属属性IndexProperty=
    DependencyProperty.Register(“索引”、typeof(int)、typeof(AlternativeItemTemplate)、新PropertyMetadata(-1));
    受保护的覆盖无效OnContainersChanged()
    {
    如果(!AssociatedObject.Items.Any()| | Index<0 | | Index>=AssociatedObject.Items.Count)
    {
    ItemContentPresenter=null;
    ItemContentControl=null;
    m_OverwriteTemplate=null;
    返回;
    }
    TryUpdateItem(ItemContainerGenerator.ContainerFromItem(AssociatedObject.Items[Index]);
    }
    私有ContentPresenter项ContentPresenter{get;set;}
    私有ContentControl项ContentControl{get;set;}
    私有数据模板m_OverwriteTemplate;
    私有void TryUpdateItem(DependencyObject itemContainer)
    {
    if(itemContainer==null)
    {
    重置模板();
    }
    var containerAsPresenter=作为ContentPresenter的itemContainer;
    if(containerAsPresenter!=null)UpdateItemContentPresenter(containerAsPresenter);
    其他的
    {
    var containerAsControl=itemContainer作为ContentControl;
    if(containerAsControl!=null)UpdateItemContentControl(containerAsControl);
    }
    }
    私有void resetOverwriteTemplate()
    {
    if(ItemContentPresenter!=null)
    ItemContentPresenter.ContentTemplate=m_OverwriteTemplate;
    if(ItemContentControl!=null)
    ItemContentControl.ContentTemplate=m_OverwriteTemplate;
    ItemContentPresenter=null;
    ItemContentControl=null;
    m_OverwriteTemplate=null;
    }
    私有void UpdateItemContentPresenter(ContentPresenter容器)
    {
    if(ItemContentPresenter!=null)
    ItemContentPresenter.ContentTemplate=m_OverwriteTemplate;
    ItemContentPresenter=容器;
    m_OverwriteTemplate=ItemContentPresenter.ContentTemplate;
    ItemContentPresenter.ContentTemplate=ItemTemplate;
    }
    私有void UpdateItemContentControl(ContentControl容器)
    {
    if(ItemContentControl!=null)
    ItemContentControl.ContentTemplate=m_OverwriteTemplate;
    ItemContentControl=容器;
    m_OverwriteTemplate=ItemContentControl.ContentTemplate;
    ItemContentControl.ContentTemplate=ItemTemplate;
    }
    }
    公共抽象类ItemContainerDecorator:行为
    {
    private Dictionary LastKnownContainers=新字典();
    受保护的ItemContainerGenerator ItemContainerGenerator{get{return(AssociatedObject!=null)?AssociatedObject.ItemContainerGenerator:null;}}
    受保护的覆盖无效附加()
    {
    base.onatached();
    ItemContainerGenerator.ItemsChanged+=初始的HandleItemsChanged;
    如果(!tryaddobserver())
    {
    AssociatedObject.Loaded+=AddObserversOnLoaded;
    }
    AssociatedObject.Loaded+=OnItemsControlled;
    AssociatedObject.LayoutUpdated+=OnItemControlLayoutUpdated;
    CheckContainersChanged();
    }
    private void OnItemControl LayoutUpdated(对象发送方,EventArgs EventArgs)
    {
    CheckContainersChanged();
    }
    已控制私有服务器(对象发送方,路由目标)
    {
    CheckContainersChanged();
    }
    private void AddObserversOnLoaded(对象发送方,RoutedEventArgs e)
    {
    AssociatedObject.Loaded-=AddObserversOnLoaded;
    tryaddobserver();
    }
    私有bool-tryaddobserver()
    {
    const bool success=true;
    小组项目=
    AssociatedObject.GetVisualDescendats().OfType().FirstOrDefault(panel=>panel.IsItemsHost);
    如果(itemsHost!=null)
    {
    var-ZingItemshost=