在WPF中如何在另一个ListBox内增加ListBox的索引?

时间:2014-11-14 18:49:39

标签: c# wpf

我希望能够访问另一个ListBox内的ListBox的索引并增加该索引。我尝试使用ItemContainerGenerator但是当我将项目转换为ListBoxItemsControl时,它会返回null

我想在后面的代码或视图模型中增加索引。

这是我模板的基本结构

<Window x:Class="WpfApplication12.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <Style x:Key="MyListStyle" TargetType="{x:Type ListBox}">

            <Setter Property="BorderThickness" Value="0"></Setter>
            <Setter Property="SelectedIndex" Value="0"></Setter>

            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel Orientation="Horizontal">

                        </VirtualizingStackPanel>
                    </ItemsPanelTemplate >
                </Setter.Value>
            </Setter>
            <Setter Property="ItemContainerStyle">
                <Setter.Value>
                    <Style TargetType="{x:Type ListBoxItem}" >
                        <Setter Property="Visibility" Value="Collapsed"></Setter>

                        <!--<Setter Property="Margin" Value="2" />-->
                        <Setter Property="Template">

                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                    <ListBox Name="InnerList" ItemsSource="{Binding}" ></ListBox>
                                </ControlTemplate>
                            </Setter.Value>

                        </Setter>
                        <Style.Triggers>
                            <Trigger Property="IsSelected" Value="true">
                                <Setter Property="Visibility" Value="Visible"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>

        <Button Grid.Row="1" Click="Button_Click">button</Button>
        <ListBox Style="{StaticResource MyListStyle}" Name="ListItemsControl" VirtualizingPanel.IsVirtualizing="True" Grid.Row="0"></ListBox>
    </Grid>
</Window>

Here is some code to load the list


        public MainWindow()
        {
            InitializeComponent();

            CompositeCollection cc = new CompositeCollection();
            cc.Add(new List<int>() { 1, 2, 3, 4, 5 });
            cc.Add(new List<int>() { 6, 7, 8, 9, 10 });
            cc.Add(new List<int>() { 11, 12, 13, 14, 15 });
            ListItemsControl.ItemsSource = cc;



        }

1 个答案:

答案 0 :(得分:1)

我建议您使用断点并浏览可视化工具(如果您想要一个变量,请使用小放大镜图标),这样您就可以了解此代码的工作原理。

将其放入按钮事件处理程序:

private void Button_Click(object sender, RoutedEventArgs e)
{
    //var item = ListItemsControl.ItemContainerGenerator.ContainerFromIndex(1) as ListBoxItem;
    //var innerListBox = VisualTreeHelper.GetChild(item, 0) as ListBox;
    //innerListBox.SelectedIndex++;

    // For every item in the ListItemsControl
    for (int i = 0; i < ListItemsControl.Items.Count; i++)
    {
        // Get the item container for the specified index and cast it as ListBoxItem.
        var item = ListItemsControl.ItemContainerGenerator.ContainerFromIndex(i) 
            as ListBoxItem;
        // Then, get the first child of the ListBoxItem and cast it as a ListBox.
        // Note that I'm making an assumption that it'll always be a ListBox,
        // which is why you should perform some checks in a production case,
        // to avoid exceptions.
        var innerListBox = VisualTreeHelper.GetChild(item, 0) as ListBox;
        // Lastly, I increment the index of this ListBox.
        innerListBox.SelectedIndex++;
    }
}

注释掉是改变一个元素的索引的方法。在下面,我正在递增所有三个内部列表框的索引。这让你知道如何到达它们,所以从那里你可以根据自己的喜好改变它。显然,您可能希望添加代码以检查null并在尝试增加SelectedIndex属性之前确认正确的类型,但这并不是很困难。

旧答案(基于第一篇文章):

这是一个代码隐藏的示例。如果您想要MVVM,请告诉我。您也可以使用BindingSelectedIndex属性,但是您必须确保已INotifyPropertyChanged已实施。

enter image description here

<强> XAML

<Window x:Class="LB.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="219.965" Width="217.535">
    <StackPanel>
        <ListBox x:Name="lbOuter" HorizontalContentAlignment="Stretch">
            <ListBox.Items>
                <TextBlock>Outer Item #1</TextBlock>
                <TextBlock>Outer Item #1</TextBlock>
                <ListBox x:Name="lbInner" BorderBrush="Black" BorderThickness="1" Margin="5">
                    <ListBox.Items>
                        <TextBlock>Inner Item #1</TextBlock>
                        <TextBlock>Inner Item #2</TextBlock>
                        <TextBlock>Inner Item #3</TextBlock>
                    </ListBox.Items>
                </ListBox>
                <TextBlock>Outer Item #3</TextBlock>
                <TextBlock>Outer Item #4</TextBlock>
            </ListBox.Items>
        </ListBox>
        <StackPanel Orientation="Horizontal">
            <Button Content="Increment Outer" Margin="5" Click="Button_Click"/>
            <Button Content="Increment Inner" Margin="5" Click="Button_Click_1"/>
        </StackPanel>
    </StackPanel>
</Window>

<强>代码隐藏

using System.Windows;

namespace LB
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (lbOuter.SelectedIndex < (lbOuter.Items.Count - 1))
            {
                lbOuter.SelectedIndex++;
            }
            else
            {
                lbOuter.SelectedIndex = 0;
            }
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            if (lbInner.SelectedIndex < (lbInner.Items.Count - 1))
            {
                lbInner.SelectedIndex++;
            }
            else
            {
                lbInner.SelectedIndex = 0;
            }
        }
    }
}

上面的代码实际上会循环你的选择。所以,如果你到达目的地,那么你需要索引0.你可以删除它,如果你不想要那个功能。