0

我正在开发一个小型 WPF 应用程序,主要包括ObservableCollection<>在其他人中显示ObservableCollection<>,等等。

这是我的应用程序的代码示例:

<Listbox Name="MainList" ItemsSource={Binding}>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>      

                <Textblock Text={Binding MainName} />
                <Button>Add item</Button>
                <Button>Delete item</Button>

                <Listbox Name="ChildList" ItemsSource="{Binding Path=ChildItem}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Textblock Text={Binding ChildName} />
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </Listbox>

            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</Listbox>

从视觉上看,它几乎是这样的:

应用示例

编辑:

我将重新解释我正在尝试做的事情。

  • 每当我单击Button AButton B我想选择MainList ListBoxItem它们所在的位置(即A Item:)

  • 每当我点击时,第二次Button B

    • 我想确保ListBoxItemChildList(图片中的第二个列表框)中选择了 a
    • 如果是这样,我想在代码隐藏中删除它。

但是我的主要问题是,由于所有内容都是由我的绑定生成的,因此到目前为止,我无法从 my 中获取一个元素,ChildList因为ChildList在我的任何MainList ListBoxItem.

4

2 回答 2

1

如果我理解得很好,问题是您希望首先单击未选中项目的按钮以选择MainItem,然后在下次单击时,当MainItem已被选中时,执行单击操作。单击按钮时尝试此操作:

private ListBoxItem FindItemContainer(DependencyObject obj)
{
   while (obj != null && !(obj is ListBoxItem))
   {
       obj = VisualTreeHelper.GetParent(obj);
   }

   if (obj != null)
       return obj as ListBoxItem;
   else
       return null;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
   var lbi = FindItemContainer(sender as DependencyObject);
   if (lbi != null)
   {
       if (lbi.IsSelected)
       {
           //do click event
       }
       else
           lbi.IsSelected = true;
   }
}

当然你也可以通过绑定来做更多的MVVM方式ListBoxItem.IsSelected让我们说bool MainItem.MyItemIsSelected

<ListBox.ItemContainerStyle>
    <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="IsSelected" Value="{Binding Path=MyItemIsSelected, Mode=TwoWay}"/>
    </Style>
</ListBox.ItemContainerStyle>

然后Button.CommandICommand MainItem.DeleteCommand执行命令时执行以下操作:

if (MyItemIsSelected)
{
    //do command body
}
else
    MyItemIsSelected = true;

从长远来看,这会更好,因为您可以复制对象SelectedItem中的行为ChildList(添加MyItemIsSelected并将其绑定到内部'ListBoxItem.IsSelected,如上所述)并将MySelectedItem属性添加到ChildList

ChildItem MySelectedItem
{
   get
   {
      return Items.FirstOrDefault(n=>n.MyItemIsSelected);
   }
}

您的删除命令如下所示:

if (MyItemIsSelected)
{
    ChildItem selItem = ChildItems.MySelectedItem;
    if (selItem != null) ChildItems.Items.Remove(selItem);
}
else
    MyItemIsSelected = true;

如果一切都是数据绑定和列表,ObservableCollections那么您可以在对象中执行所有这些操作,UI 将随之而来。实际上,您只能执行此子选择绑定位,并且仍然使用第一个解决方案,Button_Click如下所示:

private void Button_Click(object sender, RoutedEventArgs e)
{
   var lbi = FindItemContainer(sender as DependencyObject);
   if (lbi != null)
   {
       if (lbi.IsSelected)
       {
           MainItem mainItem = lbi.Content as MainItem;
           ChildItem selChild = mainItem.ChildItems.MySelectedItem;
           if (selChild != null) mainItem.ChildItems.Items.Remove(selChild);
       }
       else
           lbi.IsSelected = true;
   }
}

这是Dropbox上的简单有效示例

于 2013-05-29T06:36:20.537 回答
0

你可以在后面的代码中做任何你想做的事情:

  • 找到按下 Button 的项目:在 click 事件中,将 sender 参数强制转换为 Button 类型。它的 DataContext 属性将包含您要选择的项目。
  • 选择项目:将 MainList.SelectedItem 设置为项目。
  • 焦点将在按钮上,但这应该没问题,因为它在项目内部。
  • 在第二个列表框中查找所选项目:在 DataTemplate 中定位列表框很棘手,但您可以将其 IsSynchronizedWithCurrentItem 属性设置为 True,然后使用底层子集合的默认 CollectionView。您会像上面一样找到 MainList 的当前项目。然后你会使用:

    itemToDelete = CollectionViewSource.GetDefaultView(item.ChildItems).CurrentItem; item.ChildItems.Remove(itemToDelete);

于 2013-05-28T19:15:13.643 回答