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

发布于 2024-07-25 11:40:23 字数 2207 浏览 4 评论 0原文

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

我正在尝试使用列表视图的 ItemContainerGenerator,但它似乎不起作用。 例如,执行以下操作后 obj 为 null:

//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 中的一些项目。

为了不遗漏任何内容,ListView 使用了一些模板和拖/放功能,因此我在此处包含了 XAML。 本质上,该模板使每个项目成为一个包含一些文本的文本框 - 当选择任何项目时,该复选框就会被选中。 每个项目下面都有一个小字形来插入新项目(这一切都很好):

<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 中的一项或多项?

I'm unable to figure out how to select an item programmatically in a ListView.

I'm attempting to use the listview's ItemContainerGenerator, but it just doesn't seem to work. For example, obj is null after the following operation:

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

I've tried (based on suggestions seen here and other places) to use the ItemContainerGenerator's StatusChanged event, but to no avail. The event never fires. For example:

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

The crux of this whole thing is that I simply want to pre-select a few of the items in my ListView.

In the interest of not leaving anything out, the ListView uses some templating and Drag/Drop functionality, so I'm including the XAML here. Essentially, this template makes each item a textbox with some text - and when any item is selected, the checkbox is checked. And each item also gets a little glyph underneath it to insert new items (and this all works fine):

<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"/>

So what am I missing? How do I programmatically select one or more of the items in the ListView?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

单身狗的梦 2024-08-01 11:40:23

ListViewItemIsSelected 属性绑定到模型上的属性。 然后,您只需要使用您的模型,而不必担心 UI 的复杂性,其中包括容器虚拟化的潜在危险。

例如:

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

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

Bind the IsSelected property of the ListViewItem to a property on your model. Then, you need only work with your model rather than worrying about the intricacies of the UI, which includes potential hazards around container virtualization.

For example:

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

Now, just work with your model's IsGroovy property to select/deselect items in the ListView.

猫九 2024-08-01 11:40:23

其中“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();
     }
  }

Where 'this' is the ListView instance. This will not only change the selection, but also set the focus on the newly selected item.

  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();
     }
  }
夏至、离别 2024-08-01 11:40:23

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

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,但我发现您无法设置或添加到此项目,但希望此方法可以作为替代品。

Here would be my best guess, which would be a much simpler method for selection. Since I'm not sure what you're selecting on, here's a generic example:

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

What I'm used to seeing is a settable SelectedItem, but I see you can't set or add to this, but hopefully this method works as a replacement.

青春如此纠结 2024-08-01 11:40:23

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

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

In case you are not working with Bindings, this could also be a solution, just find the items in the source and add them to the SelectedItems property of your listview:

 lstRoomLights.ItemsSource = RoomLights;
 var selectedItems = RoomLights.Where(rl => rl.Name.Contains("foo")).ToList();
 selectedItems.ForEach(i => lstRoomLights.SelectedItems.Add(i));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文