简体   繁体   English

如何在ListView中更改用作ItemTemplate的UserControl的VisualState

[英]How to change VisualState of UserControl used as ItemTemplate in ListView

I've a UserControl with some VisualStates defined: 我有一个定义了一些VisualStatesUserControl

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

and I use it as an ItemTemplate of my ListView . 我将它用作ListViewItemTemplate When item from ListView is selected, I also want to change the VisualState of the DataTemplate . 当选择ListView中的项目时,我还想更改DataTemplateVisualState For now I've such a method: 现在我有这样一个方法:

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

It seems to work, but in some cases (listView.ContainerFromItem(item) as ListViewItem is null and therefore exception is thrown. 它似乎工作,但在某些情况下(listView.ContainerFromItem(item) as ListViewItemnull ,因此抛出异常。

Is there any other/better way to change the VisualState of used DataTemplate ? 有没有其他/更好的方法来更改使用过的DataTemplateVisualState

The reason that the item container (ie ListViewItem ) is null is because the ListView 's default panel ItemsStackPanel is a pixel-based UI virtualization panel which only renders items when they are in or close to the current viewport . 项容器(即ListViewItem )为null的原因是ListView的默认面板ItemsStackPanel是基于像素的UI虚拟化面板,它只在项目处于或接近当前视口时呈现项目。

Since you set up the selected items in code, those items might not be rendered, their containers will return as null . 由于您在代码中设置了所选项,因此可能无法呈现这些项,其容器将返回null

One simple fix would be to replace the ItemsStackPanel with a normal StackPanel , however doing this will break the built-in virtualization. 一个简单的解决方法是将ItemsStackPanel替换为普通的StackPanel ,但这样做会破坏内置的虚拟化。

Here's another solution without modifying the panel. 这是另一种不修改面板的解决方案。

First your existing code is still needed, you just need to do a null check, if the item container is null, simply do nothing. 首先,您仍需要现有代码,只需要进行空检查,如果项容器为空,则不执行任何操作。

Then, you need to subscribe to the ListView 's ContainerContentChanging event. 然后,您需要订阅ListViewContainerContentChanging事件。 This fires when the item container gets loaded. 当项目容器加载时会触发。 So basically, you check if the item that's loaded here is one of the selected items. 所以基本上,你检查这里加载的项目是否是所选项目之一。 If it is, then change its visual state. 如果是,则改变其视觉状态。 Something like this - 像这样的东西 -

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM