如何更改在 ListView 中用作 ItemTemplate 的 UserControl 的 VisualState
How to change VisualState of UserControl used as ItemTemplate in ListView
我有一个 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,因此抛出异常。
是否有任何other/better方法来改变使用的DataTemplate的VisualState?
项目容器(即 ListViewItem
)是 null
的原因是因为 ListView
的默认面板 ItemsStackPanel
是一个 像素-based UI 虚拟化 面板,仅当项目 在或接近当前视口 .
时才呈现项目
由于您在代码中设置了选定项目,这些项目可能不会呈现,它们的容器将 return 为 null
。
一个简单的修复方法是将 ItemsStackPanel
替换为正常的 StackPanel
,但是这样做会破坏内置虚拟化。
这是不修改面板的另一种解决方案。
首先你现有的代码仍然需要,你只需要做一个空检查,如果项目容器是空的,什么都不做。
然后,您需要订阅 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
}
}
我有一个 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,因此抛出异常。
是否有任何other/better方法来改变使用的DataTemplate的VisualState?
项目容器(即 ListViewItem
)是 null
的原因是因为 ListView
的默认面板 ItemsStackPanel
是一个 像素-based UI 虚拟化 面板,仅当项目 在或接近当前视口 .
由于您在代码中设置了选定项目,这些项目可能不会呈现,它们的容器将 return 为 null
。
一个简单的修复方法是将 ItemsStackPanel
替换为正常的 StackPanel
,但是这样做会破坏内置虚拟化。
这是不修改面板的另一种解决方案。
首先你现有的代码仍然需要,你只需要做一个空检查,如果项目容器是空的,什么都不做。
然后,您需要订阅 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
}
}