我有一个 UserControl ,其中定义了一些 VisualStates :
<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 ?
答案 0 :(得分:2)
项容器(即ListViewItem
)为null
的原因是ListView
的默认面板ItemsStackPanel
是基于像素的UI虚拟化面板,仅在在当前视口中或靠近当前视口时呈现项目。
由于您在代码中设置了所选项目,因此可能无法呈现这些项目,其容器将返回null
。
一个简单的解决方法是将ItemsStackPanel
替换为普通StackPanel
,但这样做会破坏内置虚拟化。
这是另一种不修改面板的解决方案。
首先你的现有代码仍然需要,你只需要进行空检查,如果项容器为空,就什么都不做。
然后,您需要订阅ListView
的{{1}}事件。当项目容器加载时会触发。所以基本上,你检查这里加载的项目是否是所选项目之一。如果是,则改变其视觉状态。像这样的东西 -
ContainerContentChanging