You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Revit API WPF C#:实现ListBox中CheckBox全选按钮功能

嘿,我看了你的代码,发现两个关键问题导致全选功能没生效,咱们来一步步搞定它:

问题分析

  1. 数据绑定不匹配:你给ListBoxItemsSourceList<string>(房间名称的字符串列表),但XAML里的CheckBoxIsChecked绑定到了{Binding IsChecked}——字符串类型根本没有IsChecked属性,所以这个绑定其实是无效的,UI上的复选框和数据完全没关联起来。
  2. 遍历对象错误:你的全选按钮事件里,尝试遍历roomlist.Items.OfType<CheckBox>(),但Items集合里存的是字符串对象,不是CheckBox控件,所以这个循环根本不会执行任何操作。

解决方案

我们需要用你已经写好的Authority类(建议改个更直观的名字,比如RoomItem)来封装房间名称和选中状态,然后修正绑定和全选逻辑:

1. 完善数据模型

把你的Authority类修改为包含房间名称的模型类,确保INotifyPropertyChanged正常工作(这样修改属性时UI会自动更新):

public class RoomItem : INotifyPropertyChanged
{
    private bool _isChecked;
    
    // 房间名称属性
    public string RoomName { get; set; }

    public bool IsChecked
    {
        get => _isChecked;
        set
        {
            _isChecked = value;
            NotifyPropertyChanged(nameof(IsChecked));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 修正构造函数的数据加载逻辑

不再直接用字符串列表,而是创建RoomItem的集合作为ListBox的数据源:

// 在窗口类里添加一个字段保存房间列表(方便后续操作)
private List<RoomItem> _roomItems;

public RoomsDistance_Form(Document doc, UIDocument uidoc)
{
    InitializeComponent();
    _uidoc = uidoc;
    _doc = doc;

    FilteredElementCollector collector = new FilteredElementCollector(doc)
        .WhereElementIsNotElementType()
        .OfCategory(BuiltInCategory.OST_Rooms);

    _roomItems = new List<RoomItem>();
    foreach (var room in collector)
    {
        _roomItems.Add(new RoomItem { RoomName = room.Name });
    }
    // 按房间名称排序
    _roomItems.Sort((x, y) => string.Compare(x.RoomName, y.RoomName));
    
    roomlist.ItemsSource = _roomItems;
}

3. 修正XAML的绑定

CheckBoxContent绑定到RoomItemRoomName属性,确保选中状态绑定正确:

<ListBox x:Name='roomlist' SelectionMode='Multiple'>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox IsChecked='{Binding IsChecked, Mode=TwoWay}' 
                      Content="{Binding RoomName}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.InputBindings>
        <KeyBinding Command="ApplicationCommands.SelectAll" Modifiers="Ctrl" Key="A" />
    </ListBox.InputBindings>
    <ListBox.CommandBindings>
        <CommandBinding Command="ApplicationCommands.SelectAll" />
    </ListBox.CommandBindings>
</ListBox>

这里加上Mode=TwoWay是为了确保UI上的手动勾选也能同步到数据模型里,后续如果需要获取选中的房间也更方便。

4. 修正全选按钮的点击事件

现在直接遍历_roomItems集合,设置每个项的IsCheckedtrue即可:

private void checkAllBtn_Click(object sender, RoutedEventArgs e)
{
    foreach (var item in _roomItems)
    {
        item.IsChecked = true;
    }
}

额外优化(可选)

如果需要实现「取消全选」或者「反选」功能,逻辑类似:

  • 取消全选:把item.IsChecked = false
  • 反选:item.IsChecked = !item.IsChecked

这样修改后,你的全选按钮就能正常工作啦,而且数据和UI也能正确同步~

内容的提问来源于stack exchange,提问作者Paslet87

火山引擎 最新活动