我正在写一个附加行为
public class resizingBehavior : Behavior<ItemsControl>
确定树视图中的可见项目数。
OnAttached方法
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;
}
当我加载应用程序和调整树视图大小时,会调用这些事件。我的问题在于计算树视图中的可见项目。不幸的是,IsVisible属性并没有给我一个正确的结果。我使用了In WPF, how can I determine whether a control is visible to the user?
中建议的答案但这似乎对我不起作用。它给了我一个错误的结果。
确定itemscontrol中实际可查看项目的任何良好实践或标准解决方案?调整大小和滚动时?顺便说一下,我正在使用反应性集合来查看我的树视图项目。
答案 0 :(得分:0)
这是工作解决方案。欢迎任何人重构和更正代码。
[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;
}
}
}