如何更改在列表视图中用作项模板的用户控件的可视状态

本文关键字:用户 控件 状态 可视 何更改 列表 视图 | 更新日期: 2023-09-27 18:36:36

我有一个定义了一些 VisualState的用户控件

<UserControl>
  <Grid Height="50" HorizontalAlignment="Stretch">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="SelectionStates">
            <VisualState x:Name="Unselected"/>
            <VisualState x:Name="Selected">
            <!-- more code -->

我将其用作我的列表视图项模板。选择列表视图中的项时,我还想更改数据模板可视状态。现在我有这样一个方法:

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,因此会引发异常。

有没有其他/更好的方法来更改使用的数据模板可视化状态

如何更改在列表视图中用作项模板的用户控件的可视状态

项目容器(即 ListViewItemnull是因为ListView的默认面板ItemsStackPanel是基于像素的 UI 虚拟化面板,它仅在项目在当前视口中或接近当前视口时呈现项目。

由于您在代码中设置了选定的项,因此这些项可能不会呈现,它们的容器将作为null返回。

一个简单的解决方法是用普通StackPanel替换ItemsStackPanel,但是这样做会破坏内置虚拟化。

这是另一种无需修改面板的解决方案。

首先你现有的代码还是需要的,你只需要做一个空检查,如果项容器是空的,干脆什么都不做。

然后,您需要订阅ListViewContainerContentChanging事件。这将在加载项容器时触发。因此,基本上,您检查此处加载的项目是否是所选项目之一。如果是,则更改其视觉状态。像这样的东西——

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
    }
}