在WPF ListView中以编程方式选择项目

23

我无法弄清如何在ListView中以编程方式选择项目。

我尝试使用ListView的ItemContainerGenerator,但似乎不起作用。例如,以下操作后obj为空:

//VariableList is derived from BindingList
m_VariableList = getVariableList();
lstVariable_Selected.ItemsSource = m_VariableList;
var obj = 
    lstVariable_Selected.ItemContainerGenerator.ContainerFromItem(m_VariableList[0]);

我尝试过(基于在此处和其他地方看到的建议)使用ItemContainerGenerator的StatusChanged事件,但没有成功。该事件从未触发。例如:

m_VariableList = getVariableList();
lstVariable_Selected.ItemContainerGenerator.StatusChanged += new EventHandler(ItemContainerGenerator_StatusChanged);
lstVariable_Selected.ItemsSource = m_VariableList;

...

void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
    //This code never gets called
    var obj = lstVariable_Selected.ItemContainerGenerator.ContainerFromItem(m_VariableList[0]);
}

整个问题的关键是我希望在我的ListView中预先选择一些项目。

为了不遗漏任何内容,这里包括XAML,该ListView使用一些模板和拖放功能。基本上,此模板使每个项目都变成带有一些文本的文本框,当选中任何项目时,复选框被选中。每个项目还会在其下方添加一个小图标以插入新项(这一切都很好地实现了)。

<DataTemplate x:Key="ItemDataTemplate_Variable">
<StackPanel>
    <CheckBox x:Name="checkbox"
        Content="{Binding Path=ListBoxDisplayName}"
        IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}, Path=IsSelected}" />
    <Image ToolTip="Insert Custom Variable" Source="..\..\Resources\Arrow_Right.gif" 
        HorizontalAlignment="Left" 
        MouseLeftButtonDown="OnInsertCustomVariable"
        Cursor="Hand" Margin="1, 0, 0, 2" Uid="{Binding Path=CmiOrder}" />
</StackPanel>
</DataTemplate>

...

<ListView Name="lstVariable_All" MinWidth="300" Margin="5"
   SelectionMode="Multiple"
   ItemTemplate="{StaticResource ItemDataTemplate_Variable}"
   SelectionChanged="lstVariable_All_SelectionChanged"
   wpfui:DragDropHelper.IsDropTarget="True" 
   wpfui:DragDropHelper.IsDragSource="True"
   wpfui:DragDropHelper.DragDropTemplate="{StaticResource ItemDataTemplate_Variable}"
       wpfui:DragDropHelper.ItemDropped="OnItemDropped"/>

那我错过了什么?我该如何以编程方式选择 ListView 中的一个或多个项目?

4个回答

37

ListViewItemIsSelected属性绑定到您模型上的一个属性上。然后,您只需要处理自己的模型,而不必担心 UI 的复杂性,包括容器虚拟化可能存在的风险。

例如:

<ListView>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="IsSelected" Value="{Binding IsGroovy}"/>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

现在,只需使用您的模型的IsGroovy属性,在ListView中选择/取消选择项目即可。


2
当然。数据绑定。WPF中的所有问题归结为数据绑定,不是吗?谢谢,肯特。 - Paul Prewett
这是一个非常棒的解决方案,赞! - Louis Kottmann
4
请注意:此解决方案不适用于Windows Store应用程序。相反,您应该在代码后台中设置绑定,就像这样:http://social.msdn.microsoft.com/Forums/windowsapps/en-US/9a0adf35-fdad-4419-9a34-a9dac052a2e3/listviewitemisselected-data-binding-in-style-setter-is-not-working?forum=winappswithcsharp - SimonFisher

6

其中,“this”是ListView实例。这不仅会更改选择,还会将焦点设置在新选定的项上。

  private void MoveSelection(int level)
  {
     var newIndex = this.SelectedIndex + level;
     if (newIndex >= 0 && newIndex < this.Items.Count)
     {
        this.SelectedItem = this.Items[newIndex];
        this.UpdateLayout();
        ((ListViewItem)this.ItemContainerGenerator.ContainerFromIndex(newIndex)).Focus();
     }
  }

3

以下是我最好的猜测,这是一种更简单的选择方法。由于我不确定您在选择什么,这里提供一个通用示例:

var indices = new List<int>();

for(int i = 0; i < lstVariable_All.Items.Count; i++)
{
  // If this item meets our selection criteria 
  if( lstVariable_All.Items[i].Text.Contains("foo") )
    indices.Add(i);
}

// Reset the selection and add the new items.
lstVariable_All.SelectedIndices.Clear();

foreach(int index in indices)
{
  lstVariable_All.SelectedIndices.Add(index);
}

通常我所见到的是可设置的SelectedItem,但是我发现你不能设置或添加它,但希望这种方法可以作为替代方案。


1

如果您没有使用绑定,这也可以是一种解决方案,只需在源中找到项目并将它们添加到您的列表视图的SelectedItems属性中:

 lstRoomLights.ItemsSource = RoomLights;
 var selectedItems = RoomLights.Where(rl => rl.Name.Contains("foo")).ToList();
 selectedItems.ForEach(i => lstRoomLights.SelectedItems.Add(i));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接