【问题标题】:Iterate through listbox not returning correctly?遍历列表框未正确返回?
【发布时间】:2012-01-09 17:21:29
【问题描述】:

我有一个复选框列表框,我想遍历并选中它们,然后取消选中它们。我还需要找到稍后检查的那些。这是我的代码:

<StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock Style="{StaticResource TextLabel}" Text="Building Houses Organization:"></TextBlock>
        <TextBlock Text="All" Margin="136,0,0,0" Foreground="#FF001BFF" FontSize="11" VerticalAlignment="Center" Tag="{Binding ElementName=BuildingsOrganizationList}" MouseLeftButtonDown="CheckAll"/>
        <TextBlock Text=" | " VerticalAlignment="Center"/>
        <TextBlock Text="None" Foreground="#FF001BFF" FontSize="11" VerticalAlignment="Center" Tag="{Binding ElementName=BuildingsOrganizationList}" MouseLeftButtonDown="CheckNone"/>
    </StackPanel>
    <ListBox x:Name="BuildingsOrganizationList" HorizontalAlignment="Left" VerticalAlignment="Top" Width="{Binding ActualWidth, ElementName=BuildingOrganizationGrid, Mode=OneWay}" Height="141">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox Content="{Binding}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>

你可以看到我的文本块有一个标签绑定到我的列表框,其中包含我的复选框。现在在后面的代码中我有以下内容:

private void CheckAll(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    TextBlock textblock = sender as TextBlock;
    ListBox list = textblock.Tag as ListBox;
    foreach (ListBoxItem item in list.Items)
    {
        //.....
    }
}

问题是项目是字符串。它们不是 ListBoxItem 或 CheckBox 对象。这是为什么呢?

编辑

我现在已经添加了这个类

class ListItem
{
    private string _name;
    private bool? _isChecked;

    public ListItem()
    {
        _name = "";
        _isChecked = null;
    }

    public ListItem(string name, bool? isChecked)
    {
        Name = name;
        IsChecked = isChecked;
    }

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public bool? IsChecked
    {
        get { return _isChecked; }
        set { _isChecked = value; }
    }
}

并有以下几行来填充我的列表

BuildingsOrganizationList.Items.Add(new ListItem(org, true));

还有 XAML:

    <ListBox x:Name="BuildingsOrganizationList" HorizontalAlignment="Left" VerticalAlignment="Top" Width="{Binding ActualWidth, ElementName=BuildingOrganizationGrid, Mode=OneWay}" Height="141">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

但是,我的复选框没有被选中,也没有文字。

【问题讨论】:

    标签: c# .net wpf silverlight xaml


    【解决方案1】:

    我的猜测是因为您使用了BuildingsOrganizationList.Items.Add(someString) 来用项目填充您的 ListBox。

    ListBox.Items 将返回绑定到您的 ListBox 的数据对象,而不是 UI 对象。因此,如果您的数据对象是字符串,那么 ListBox.Items 将返回一个字符串集合。如果要获取与数据对象相关的UI对象,需要使用ListBox的ItemContainerGenerator并调用.ContainerFromItem(dataItem)

    最好用具有IsChecked 属性的对象填充ListBox,并绑定CheckBoxIsChecked 值。这是因为默认情况下,WPF 将使用虚拟化 ListBoxes,它会在您滚动时回收 UI 控件,这意味着 CheckBoxes 将丢失其 IsChecked 值,除非它们绑定到某些东西。

    例如,

    BuildingsOrganizationList.Items.Add(new SomeItem { Name="A", IsChecked=false });
    BuildingsOrganizationList.Items.Add(new SomeItem { Name="B", IsChecked=false });
    BuildingsOrganizationList.Items.Add(new SomeItem { Name="C", IsChecked=false });
    

    ListBox 的数据模板

    <DataTemplate>
        <CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" />
    </DataTemplate>
    

    然后你可以使用

    private void CheckAll(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        foreach (SomeItem item in BuildingsOrganizationList.Items)
        {
            item.IsChecked = true;
        }
    }
    

    【讨论】:

    • 类似的东西。我有一个可观察的字符串集合,并将其设置为 itemsource。更好的方法是什么?
    • @Justin 更好的方法是使用ObservableCollection&lt;SomeItem&gt;,其中SomeItem 包含IsCheckedContent 的属性
    • 奇怪的是,我的复选框现在旁边没有文字,现在设置了你描述的方式。
    • @Justin 您要绑定的对象的属性名称是否与您的CheckBox 中的Content 绑定相匹配?
    • @Justin 您发布的代码对我来说很好,尽管我建议让ListItem 实现INotifyPropertyChanged,这样当您更改IsChecked 的值时,它会自动告诉用户界面进行更新
    【解决方案2】:

    我们怎么知道?您添加了项目,并将它们绑定到 CheckBoxesContent,这意味着您的项目变成了 CheckBoxes

    如果你想访问模板的CheckBox,虽然你可以通过各种讨厌的方式获得它,我推荐任何方式。

    将项目类型更改为具有bool 属性的某个类,该属性将can be bound 更改为CheckBox.IsChecked。更干净,更容易处理。一般来说,大多数时候您不需要在代码中引用任何实际控件,请尝试绑定必要的属性。 (也不需要对 ListBox 的引用:绑定ListBox.ItemsSource,对其进行迭代,更改项目的属性)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-10
      • 2018-11-12
      • 1970-01-01
      • 2018-03-03
      • 2020-06-18
      • 2013-08-12
      • 2013-07-13
      相关资源
      最近更新 更多