如何根据列表中是否存在绑定对象来设置 CheckBox.IsChecked

发布于 2024-10-15 07:39:57 字数 1949 浏览 5 评论 0原文

有 2 个列表——AvailableItems 和 SelectedItems。

AvailableItems 显示在一个 ListBox 中,每个 ListBoxItem 都包含一个 CheckBox。目的是如果绑定项位于 SelectedItems 中,则检查 CheckBox。

我可以在不处理代码隐藏中的 Checked 和 Unchecked 且不向项目类添加 IsSelected 属性的情况下实现此目的吗?

这是到目前为止的 XAML:

   <ListBox Name="ListBox1" ItemsSource="{Binding Path=AvailableItems}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel></StackPanel>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <DockPanel>
                    <CheckBox Name="cb1"></CheckBox>
                    <TextBlock Text="{Binding}"></TextBlock>
                </DockPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ListBox>

和隐藏代码:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            _availableItems.Add(Colors.Red);
            _availableItems.Add(Colors.Green);
            _availableItems.Add(Colors.Blue);

            _selectedItems.Add(Colors.Green);

            this.DataContext = this;
        }

        ObservableCollection<Color> _selectedItems = new ObservableCollection<Color>();
        public ObservableCollection<Color> SelectedItems
        {
            get { return _selectedItems; }
            set { _selectedItems = value; }
        }

        ObservableCollection<Color> _availableItems = new ObservableCollection<Color>();
        public ObservableCollection<Color> AvailableItems
        {
            get { return _availableItems; }
            set { _availableItems = value; }
        }
    }

可以将上面的 xaml/代码直接复制到新的 WPF 项目中进行测试。

There are 2 lists - AvailableItems and SelectedItems.

AvailableItems is displayed in a ListBox, and each ListBoxItem contains a CheckBox. The intention is that the CheckBox is checked if the bound item is in SelectedItems.

Can I achieve this without handling Checked and Unchecked in the code-behind, and without adding an IsSelected property to my item class?

Here's the XAML so far:

   <ListBox Name="ListBox1" ItemsSource="{Binding Path=AvailableItems}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel></StackPanel>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <DockPanel>
                    <CheckBox Name="cb1"></CheckBox>
                    <TextBlock Text="{Binding}"></TextBlock>
                </DockPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ListBox>

and the code-behind:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            _availableItems.Add(Colors.Red);
            _availableItems.Add(Colors.Green);
            _availableItems.Add(Colors.Blue);

            _selectedItems.Add(Colors.Green);

            this.DataContext = this;
        }

        ObservableCollection<Color> _selectedItems = new ObservableCollection<Color>();
        public ObservableCollection<Color> SelectedItems
        {
            get { return _selectedItems; }
            set { _selectedItems = value; }
        }

        ObservableCollection<Color> _availableItems = new ObservableCollection<Color>();
        public ObservableCollection<Color> AvailableItems
        {
            get { return _availableItems; }
            set { _availableItems = value; }
        }
    }

The above xaml/code can be copied straight into a new WPF project for testing.

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

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

发布评论

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

评论(2

雨落星ぅ辰 2024-10-22 07:39:57

您定义一个多值转换器,它接受一个项目和一个集合并返回一个布尔值:

public class CollectionContainsConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var item = values[0];
        var collection = values[1] as IList;
        return collection.Contains(item);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

然后像这样使用它:

    <ListBox Name="ListBox1" ItemsSource="{Binding Path=AvailableItems}">
        <ListBox.Resources>
            <local:CollectionContainsConverter x:Key="contains"/>
        </ListBox.Resources>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel></StackPanel>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <DockPanel>
                    <CheckBox Name="cb1">
                        <CheckBox.IsChecked>
                            <MultiBinding Converter="{StaticResource contains}" Mode="OneWay">
                                <Binding Mode="OneWay"/>
                                <Binding ElementName="ListBox1" Path="DataContext.SelectedItems" Mode="OneWay"/>
                            </MultiBinding>
                        </CheckBox.IsChecked>
                    </CheckBox>
                    <TextBlock Text="{Binding}"></TextBlock>
                </DockPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ListBox>

处理反向转换留作练习。

You define a multi value converter that takes an item and a collection and returns a boolean:

public class CollectionContainsConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var item = values[0];
        var collection = values[1] as IList;
        return collection.Contains(item);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

and then you use it like this:

    <ListBox Name="ListBox1" ItemsSource="{Binding Path=AvailableItems}">
        <ListBox.Resources>
            <local:CollectionContainsConverter x:Key="contains"/>
        </ListBox.Resources>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel></StackPanel>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <DockPanel>
                    <CheckBox Name="cb1">
                        <CheckBox.IsChecked>
                            <MultiBinding Converter="{StaticResource contains}" Mode="OneWay">
                                <Binding Mode="OneWay"/>
                                <Binding ElementName="ListBox1" Path="DataContext.SelectedItems" Mode="OneWay"/>
                            </MultiBinding>
                        </CheckBox.IsChecked>
                    </CheckBox>
                    <TextBlock Text="{Binding}"></TextBlock>
                </DockPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ListBox>

Handling the reverse conversion is left as an exercise.

掩饰不了的爱 2024-10-22 07:39:57

使用 MVVM 进行粗略模型

创建一个类来表示每个项目所需的所有数据,例如 Checked 和描述

class CustomItem : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private bool _isSelected;
        private string _customColour;

        public bool IsSelected
        {
            get { return _isSelected; }
            set 
            { 
                _isSelected = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged.Invoke(this, new PropertyChangedEventArgs("IsSelected"));
                }
            }
        }

        public string CustomColour
        {
            get { return _customColour; }
            set
            {
                _customColour = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged.Invoke(this, new PropertyChangedEventArgs("CustomColour"));
                }
            }
        }        
    }

创建一个类来表示您想要显示的项目集合

   class CustomItems : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private ObservableCollection<CustomItem> _listOfCustomItems;

        public CustomItems()
        {
            ListOfCustomItems = new ObservableCollection<CustomItem>();

            var c = new CustomItem
                        {
                            IsSelected = false, 
                            CustomColour = "Red"
                        };
            ListOfCustomItems.Add(c); 

            c = new CustomItem
                    {
                        IsSelected = true, 
                        CustomColour = "Green"
                    };
            ListOfCustomItems.Add(c);

            c = new CustomItem
                    {
                        IsSelected = false, 
                        CustomColour = "Blue"
                    };

            ListOfCustomItems.Add(c);
        }

        public ObservableCollection<CustomItem> ListOfCustomItems
        {
            get { return _listOfCustomItems; }
            set 
            { 
                _listOfCustomItems = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged.Invoke(this, new PropertyChangedEventArgs("ListOfCustomItems"));
                }
            }
        }

        public List<CustomItem> SelectedItems
        {
            get
            {
                return (from customItem in ListOfCustomItems 
                        where customItem.IsSelected 
                        select customItem).ToList();
            }
        }
    }

添加到窗口

 <Window.Resources>
        <WpfApplication1:CustomItems x:Key="CI"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource CI}">
        <ListBox ItemsSource="{Binding Path=ListOfCustomItems}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel></StackPanel>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <DockPanel>
                        <CheckBox IsChecked="{Binding Path=IsSelected}"/>
                        <TextBlock Text="{Binding Path=CustomColour}"/>
                    </DockPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ListBox>
    </Grid>

您维护一个项目列表,并提供一个属性获取执行简单 LINQ 选择的选定内容。简单的。根据需要更改数据类型。

A rough mock up using MVVM

create a class to represent all the data you need for each item eg Checked and description

class CustomItem : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private bool _isSelected;
        private string _customColour;

        public bool IsSelected
        {
            get { return _isSelected; }
            set 
            { 
                _isSelected = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged.Invoke(this, new PropertyChangedEventArgs("IsSelected"));
                }
            }
        }

        public string CustomColour
        {
            get { return _customColour; }
            set
            {
                _customColour = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged.Invoke(this, new PropertyChangedEventArgs("CustomColour"));
                }
            }
        }        
    }

create a class to represent the item collection you want displayed

   class CustomItems : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private ObservableCollection<CustomItem> _listOfCustomItems;

        public CustomItems()
        {
            ListOfCustomItems = new ObservableCollection<CustomItem>();

            var c = new CustomItem
                        {
                            IsSelected = false, 
                            CustomColour = "Red"
                        };
            ListOfCustomItems.Add(c); 

            c = new CustomItem
                    {
                        IsSelected = true, 
                        CustomColour = "Green"
                    };
            ListOfCustomItems.Add(c);

            c = new CustomItem
                    {
                        IsSelected = false, 
                        CustomColour = "Blue"
                    };

            ListOfCustomItems.Add(c);
        }

        public ObservableCollection<CustomItem> ListOfCustomItems
        {
            get { return _listOfCustomItems; }
            set 
            { 
                _listOfCustomItems = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged.Invoke(this, new PropertyChangedEventArgs("ListOfCustomItems"));
                }
            }
        }

        public List<CustomItem> SelectedItems
        {
            get
            {
                return (from customItem in ListOfCustomItems 
                        where customItem.IsSelected 
                        select customItem).ToList();
            }
        }
    }

Add to window

 <Window.Resources>
        <WpfApplication1:CustomItems x:Key="CI"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource CI}">
        <ListBox ItemsSource="{Binding Path=ListOfCustomItems}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel></StackPanel>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <DockPanel>
                        <CheckBox IsChecked="{Binding Path=IsSelected}"/>
                        <TextBlock Text="{Binding Path=CustomColour}"/>
                    </DockPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ListBox>
    </Grid>

You maintain a single list of items, and supply a property to get the selected ones which does a simple LINQ select. Easy. Change datatypes as you need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文