在我们的C# WPF
应用中(带有Caliburn.Micro
),我们有一个带有一些TextBox,Dropdown等视图。我们还有一些ViewModel列表,其中包含一个按钮,可以将其他项添加到这些单独的ItemsControl列表中。对于此View,我们创建了一个行为,其行为如下:
这是按预期工作的。我们现在遇到的问题是它还会将焦点转移到View的最后一个ItemsControl的第一项,即我们刷新数据的那一刻。数据刷新是必需的,所以现在我们有以下两个选项之一:
这两个选项都不是真的可以解决,所以我想修改行为,这样它只会在我们使用其中一个按钮添加项目时触发,而不是在数据刷新时触发。
以下是行为的代码:
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace NatWa.MidOffice.Behaviors
{
public class FocusSpecificBehavior : Behavior<ItemsControl>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += ItemsControlLoaded;
}
protected override void OnDetaching()
{
base.OnDetaching();
((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged -= CollectionChanged;
}
private void ItemsControlLoaded(object sender, RoutedEventArgs e)
{
AssociatedObject.Loaded -= ItemsControlLoaded;
((INotifyCollectionChanged)AssociatedObject.Items).CollectionChanged += CollectionChanged;
}
private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action != NotifyCollectionChangedAction.Add || AssociatedObject.Items.Count == 0) return;
var lastItem = (FrameworkElement)AssociatedObject.ItemContainerGenerator.ContainerFromIndex(AssociatedObject.Items.Count - 1);
if (lastItem == null) return;
if (lastItem.IsLoaded)
SetFocus(lastItem);
lastItem.Loaded += SetFocus;
}
private static void SetFocus(object sender, RoutedEventArgs e)
{
if (sender == null) return;
var lastItem = (FrameworkElement)sender;
lastItem.Loaded -= SetFocus;
SetFocus(lastItem);
}
private static void SetFocus(UIElement item)
{
item.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
}
}
因此,当ItemsControl列表中的某些内容发生更改时,我们会进入上面的CollectionChanged
方法。我在其中放置了一个断点进行一些测试。重新加载数据时,它也会不幸地引发NotifyCollectionChangedAction.Add
。我还检查了我是否可以对从Count
检索到的ItemsControl /列表的sender
和从Args e
检索到的当前索引执行某些操作,但{{1}在刷新数据或添加新项目时,sender
看起来完全相同。
那么,有没有人知道如何修改这个行为,所以它集中了ItemsControl的添加项,但同时它不会触发数据刷新/重置?