我有一个绑定到可观察集合的树视图。集合中的每个项目都有一个带有项目的可观察集合。
public class Item
{
public ObservableCollection<Item> Items { get; set; }
public Item Parent { get; set; }
}
public Item Root { get; set; }
<TreeView ItemsSource={Binding Root.Items}>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Items}">
<TextBlock Text="{Binding}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
我想将树中的一个节点从一个分支移动到另一个分支,但这样做会使控件松散焦点和选择。
UnindentItemCommand = new DelegateCommand<Item>(
item =>
{
var parent = item.Parent;
parent.Items.Remove(item);
parent.parent.Items.Add(item);
}
);
我尝试使用another question中的BindableSelectedItemBehavior
,但它无济于事。
有人有解决方法吗?
答案 0 :(得分:1)
如何从视图模型或后面的代码绑定到TreeView.SelectedItem
属性?:
<TreeView ItemsSource="{Binding Root.Items}" TreeView.SelectedItem="{Binding Item}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Items}">
<TextBlock Text="{Binding}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
然后在您的节点移动代码中,您可以获取所选项目的副本,并在移动数据时重新设置它:
UnindentItemCommand = new DelegateCommand<Item>(
item =>
{
Item selectedItem = Item;
var parent = item.Parent;
parent.Items.Remove(item);
parent.parent.Items.Add(item);
Item = selectedItem;
}
);
答案 1 :(得分:0)
我遇到了完全相同的问题。在我看来,这确实是WPF中的错误。移动可观察集合中的节点后,树将正确更新并选择了正确的节点,但是键盘焦点丢失了。对我有用的是,通过获取第一个treeviewitem元素并明确地将焦点设置在树上,来“摇晃”一下树。然后,我将简单地转到我移动的元素,并将IsSelected属性设置为false,然后设置为true,这将使焦点重新回到它上面。这不是最优雅的解决方案,但是与我尝试过的所有其他解决方案相比,它非常简单,并且对最终用户而言看起来都是无缝的。
UnindentItemCommand = new DelegateCommand<Item>(
item =>
{
Item selectedItem = Item;
var parent = item.Parent;
parent.Items.Remove(item);
parent.parent.Items.Add(item);
Item = selectedItem;
TreeViewItem tvi = (TreeViewItem)
(TreeName.ItemContainerGenerator.ContainerFromItem(TreeName.Items[0]));
tvi.Focus();
Keyboard.Focus(tvi);
Item.IsSelected= false;
Item.IsSelected = true;
}
);
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />