C# WPF Treeview项目可见性附加行为

C# WPF Treeview项目可见性附加行为,c#,wpf,xaml,mvvm,treeview,C#,Wpf,Xaml,Mvvm,Treeview,我在写一个附加的行为 公共类大小调整行为:行为 确定树状视图中可见项目的数量 附加法 protected override void OnAttached() { base.OnAttached(); AssociatedObject.Loaded += AssociatedObject_Loaded; } 在AssociatedObject.Loaded内部事件处理程序 我正在为我的treeview控件挂接一个大小更改的事件处理程序 private void Associated

我在写一个附加的行为

公共类大小调整行为:行为

确定树状视图中可见项目的数量

附加法

protected override void OnAttached()
{
   base.OnAttached();
   AssociatedObject.Loaded += AssociatedObject_Loaded;
}
AssociatedObject.Loaded内部
事件处理程序

我正在为我的treeview控件挂接一个大小更改的事件处理程序

private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
   var itemsControl = (ItemsControl)sender;

   _sizeChangedEventHandler = (s, f) => ComputeVisibleItemsCount(itemsControl);

   var treeListView = AssociatedObject as TreeListView;        
   treeListView.SizeChanged += _sizeChangedEventHandler;

   itemsControl.Loaded -= AssociatedObject_Loaded;
}
当我加载我的应用程序和调整我的treeview时,会调用这些事件。我的问题是计算树视图中的可见项。不幸的是,IsVisible属性没有给出正确的结果。我使用了中建议的答案

但这似乎对我不起作用。这给了我一个错误的结果


确定itemscontrol中的实际可视项是否有良好的做法或标准解决方案?调整大小和滚动时?顺便说一句,我正在对我的treeview项目使用反应式收集。

以下是有效的解决方案。欢迎任何人重构和更正代码

[Localizable(false)]
public class ItemsControlResizingBehavior : Behavior<ItemsControl>
{
    public static readonly DependencyProperty VisibleItemsCountProperty =
        DependencyProperty.Register("VisibleItemsCount",
            typeof(int),
            typeof(ItemsControlResizingBehavior),
            new FrameworkPropertyMetadata(0, OnSizeChanged));

    public int VisibleItemsCount
    {
        get { return (int)GetValue(VisibleItemsCountProperty); }
        set { SetValue(VisibleItemsCountProperty, value); }
    }

    private static void OnSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue == null)
            return;
        var behavior = (ItemsControlResizingBehavior)d;

        if (behavior.AssociatedObject == null)
            return;

        behavior.ComputeVisibleItemsCount(behavior.AssociatedObject);
    }

    private SizeChangedEventHandler _listViewSizeChangedEventHandler;

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Loaded += AssociatedObject_Loaded;
    }

    private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
    {
        var itemsControl = (ItemsControl)sender;

        _listViewSizeChangedEventHandler = (x, y) => ComputeVisibleItemsCount(itemsControl);

        var treeListView = AssociatedObject as TreeListView;
        if (treeListView != null)
            treeListView.SizeChanged += _listViewSizeChangedEventHandler;

        var listView = AssociatedObject as ListView;
        if (listView != null)
            listView.SizeChanged += _listViewSizeChangedEventHandler;

        itemsControl.Loaded -= AssociatedObject_Loaded;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();

        var treeListView = AssociatedObject as TreeListView;
        if (treeListView != null)
            treeListView.SizeChanged -= _listViewSizeChangedEventHandler;

        var listView = AssociatedObject as ListView;
        if (listView != null)
            listView.SizeChanged -= _listViewSizeChangedEventHandler;
    }

    private void ComputeVisibleItemsCount(ItemsControl itemsControl)
    {
        if (itemsControl.Items.Count <= 0)
            return;

        if (itemsControl is TreeListView)
        {
            VisibleItemsCount = GetTreeViewItems(itemsControl).Count(x => x.IsVisibleInUI(itemsControl));
        }
        if (itemsControl is ListView)
        {
            VisibleItemsCount = GetListViewItems(itemsControl).Count(x => x.IsVisibleInUI(itemsControl));
        }
    }

    private static IEnumerable<TreeViewItem> GetTreeViewItems(ItemsControl tree)
    {
        for (int i = 0; i < tree.Items.Count; i++)
        {
            var item = (TreeViewItem)tree.ItemContainerGenerator.ContainerFromIndex(i);
            if (item == null)
                continue;

            yield return item;

            foreach (TreeViewItem subItem in GetTreeViewItems(item))
            {
                yield return subItem;
            }
        }
    }

    private static IEnumerable<ListViewItem> GetListViewItems(ItemsControl list)
    {
        for (int i = 0; i < list.Items.Count; i++)
        {
            var item = (ListViewItem)list.ItemContainerGenerator.ContainerFromIndex(i);
            if (item == null)
                continue;

            yield return item;
        }
    }
}
[可本地化(错误)]
公共类项ControlResizengBehavior:行为
{
公共静态只读从属属性VisibleItemsCountProperty=
DependencyProperty.Register(“VisibleItemsCount”,
类型(int),
类型(项目控制调整行为),
新的FrameworkPropertyMetadata(0,OnSizeChanged));
公共int VisibleItemsCount
{
获取{return(int)GetValue(VisibleItemsCountProperty);}
set{SetValue(VisibleItemsCountProperty,value);}
}
IzeChanged上的私有静态无效(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
如果(e.NewValue==null)
返回;
变量行为=(ItemsControlResizengBehavior)d;
if(behavior.AssociatedObject==null)
返回;
behavior.ComputeVisibleItemsCount(behavior.AssociatedObject);
}
私有SizeChangedEventHandler _listViewSizeChangedEventHandler;
受保护的覆盖无效附加()
{
base.onatached();
AssociatedObject.Loaded+=AssociatedObject\u Loaded;
}
已加载关联对象的私有无效(对象发送方,路由目标)
{
var itemsControl=(itemsControl)发送方;
_listViewSizeChangedEventHandler=(x,y)=>ComputeVisibleItemsCount(itemsControl);
var treeListView=作为treeListView的关联对象;
如果(treeListView!=null)
treeListView.SizeChanged+=\u listViewSizeChangedEventHandler;
var listView=与listView关联的对象;
如果(listView!=null)
listView.SizeChanged+=\u listViewSizeChangedEventHandler;
itemsControl.Loaded-=AssociatedObject\u Loaded;
}
附加时受保护的覆盖无效()
{
base.OnDetaching();
var treeListView=作为treeListView的关联对象;
如果(treeListView!=null)
treeListView.SizeChanged-=\u listViewSizeChangedEventHandler;
var listView=与listView关联的对象;
如果(listView!=null)
listView.SizeChanged-=\u listViewSizeChangedEventHandler;
}
私有void ComputeVisibleItemsCount(ItemsControl ItemsControl)
{
if(itemsControl.Items.Count x.IsVisibleInUI(itemsControl));
}
如果(itemsControl为ListView)
{
VisibleItemsCount=GetListViewItems(itemsControl).Count(x=>x.IsVisibleInUI(itemsControl));
}
}
私有静态IEnumerable GetTreeViewItems(ItemsControl树)
{
对于(int i=0;i