将ItemsControl中的一个新项目滚动到视图中 [英] Scroll a new item in a ItemsControl into view

查看:125
本文介绍了将ItemsControl中的一个新项目滚动到视图中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ItemsControl ,它是数据绑定到一个 ObservableCollection 。我在代码背后有这个方法,在列表中添加一个新的模型。我想将新项目(列表底部)滚动到视图中。



我认为 ItemsControl 在查询大小时尚未更新,因为添加模型之前和之后的 ActualHeight 是相同的。此代码的效果是滚动到略高于新项目的点。



我如何知道新的 ActualHeight 将是?



这是我的代码:

  ViewModel.CreateNewChapter(); 
var height = DocumentElements.ActualHeight;
var width = DocumentElements.ActualWidth;
DocumentElements.BringIntoView(new Rect(0,height - 1,width,1));


解决方案

我想你需要调用 BringIntoView 在项目容器上,而不是ItemsControl本身:

  var container = DocumentElements.ItemContainerGenerator。 ContainerFromItem(model)as FrameworkElement; 
if(container!= null)
container.BringIntoView();






编辑:实际上这不行,因为在这一点上,项目容器尚未生成...您可以处理 ItemContainerGenerator StatusChanged 事件c>。我尝试了以下代码:

  public static class ItemsControlExtensions 
{
public static void BringItemIntoView(this ItemsControl itemsControl,object item)
{
var generator = itemsControl.ItemContainerGenerator;

if(!TryBringContainerIntoView(generator,item))
{
EventHandler handler = null;
handler =(sender,e)=>
{
switch(generator.Status)
{
case GeneratorStatus.ContainersGenerated:
TryBringContainerIntoView(generator,item);
break;
case GeneratorStatus.Error:
generator.StatusChanged - = handler;
break;
case GeneratorStatus.GeneratingContainers:
return;
case GeneratorStatus.NotStarted:
return;
默认值:
break;
}
};

generator.StatusChanged + = handler;



private static bool TryBringContainerIntoView(ItemContainerGenerator生成器,对象项)
{
var container = generator.ContainerFromItem(item)as FrameworkElement;
if(container!= null)
{
container.BringIntoView();
返回true;
}
返回false;
}
}

但是它不适用于...某些原因, ContainerFromItem 在状态更改为 ContainersGenerated 后仍返回null,我不知道为什么: p>




编辑:好的,我现在明白了...这是因为虚拟化:容器只有当他们需要被显示,所以不会为隐藏的物品生成容器。如果您为ItemsControl( VirtualizingStackPanel.IsVirtualizing =False)切换虚拟化,上述解决方案可以正常运行。


I have an ItemsControl that is databound to a ObservableCollection. I have this method in the code behind which adds a new model to the list. I would then like to scroll the new item (at the bottom of the list) into view.

I think the size of the ItemsControl is not yet updated when I am querying the size, since the ActualHeight before and after the addition of the model is the same. The effect of this code is to scroll to a point slightly above the new item.

How would I know what the new ActualHeight is going to be?

Here is my code:

        ViewModel.CreateNewChapter();
        var height = DocumentElements.ActualHeight;
        var width = DocumentElements.ActualWidth;
        DocumentElements.BringIntoView(new Rect(0, height - 1, width, 1));

解决方案

I think you need to call BringIntoView on the item container, not the ItemsControl itself :

var container = DocumentElements.ItemContainerGenerator.ContainerFromItem(model) as FrameworkElement;
if (container != null)
    container.BringIntoView();


EDIT: actually this doesn't work, because at this point, the item container hasn't been generated yet... You could probably handle the StatusChanged event of the ItemContainerGenerator. I tried the following code :

public static class ItemsControlExtensions
{
    public static void BringItemIntoView(this ItemsControl itemsControl, object item)
    {
        var generator = itemsControl.ItemContainerGenerator;

        if (!TryBringContainerIntoView(generator, item))
        {
            EventHandler handler = null;
            handler = (sender, e) =>
            {
                switch (generator.Status)
                {
                    case GeneratorStatus.ContainersGenerated:
                        TryBringContainerIntoView(generator, item);
                        break;
                    case GeneratorStatus.Error:
                        generator.StatusChanged -= handler;
                        break;
                    case GeneratorStatus.GeneratingContainers:
                        return;
                    case GeneratorStatus.NotStarted:
                        return;
                    default:
                        break;
                }
            };

            generator.StatusChanged += handler;
        }
    }

    private static bool TryBringContainerIntoView(ItemContainerGenerator generator, object item)
    {
        var container = generator.ContainerFromItem(item) as FrameworkElement;
        if (container != null)
        {
            container.BringIntoView();
            return true;
        }
        return false;
    }
}

However it doesn't work either... for some reason, ContainerFromItem still returns null after the status changes to ContainersGenerated, and I have no idea why :S


EDIT : OK, I understand now... this was because of the virtualization : the containers are generated only when they need to be displayed, so no containers are generated for hidden items. If you switch virtualization off for the ItemsControl (VirtualizingStackPanel.IsVirtualizing="False"), the solution above works fine.

这篇关于将ItemsControl中的一个新项目滚动到视图中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆