我有一个定义了一些 VisualStates 的 UserControl:
<UserControl>
<Grid Height="50" HorizontalAlignment="Stretch">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<!-- more code -->
我将它用作我的 ListView 的 ItemTemplate。选择 ListView 中的项目时,我还想更改 DataTemplate 的 VisualState。现在我有这样一个方法:
private void list_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListView listView = sender as ListView;
foreach (var item in e.AddedItems)
VisualStateManager.GoToState((listView.ContainerFromItem(item) as ListViewItem).ContentTemplateRoot as myControl, "Selected", false);
}
它似乎有效,但在某些情况下 (listView.ContainerFromItem(item) as ListViewItem
为 null,因此抛出异常。
是否有任何其他/更好的方法来更改使用过的 DataTemplate 的 VisualState?
最佳答案
项目容器(即 ListViewItem
)为 null
的原因是 ListView
的默认面板 ItemsStackPanel
是一个基于像素的 UI 虚拟化面板,它仅在项目位于或靠近当前视口(viewport)时呈现项目。
由于您在代码中设置了选定项,因此这些项可能不会呈现,它们的容器将返回为 null
。
一个简单的修复方法是用普通的 StackPanel
替换 ItemsStackPanel
,但是这样做会破坏内置的虚拟化。
这是不修改面板的另一种解决方案。
首先你现有的代码仍然需要,你只需要做一个空检查,如果项目容器是空的,什么都不做。
然后,您需要订阅ListView
的ContainerContentChanging
事件。当项目容器被加载时会触发。所以基本上,您检查此处加载的项目是否是所选项目之一。如果是,则更改其视觉状态。像这样的 -
private void MyListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (this.MyListView.SelectedItems.Contains(args.Item))
{
// get the container
var container = (ListViewItem)args.ItemContainer;
// do your visual state change here, when the container was previously null
}
}
关于c# - 如何更改在 ListView 中用作 ItemTemplate 的 UserControl 的 VisualState,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27813842/