3

让我先声明我对 C# 和 WPF 都很陌生,以此作为这个问题的前缀。

我正在尝试将一组Boolean值连接到包含 6 个复选框的容器,并在按下按钮时存储这些值的状态。我假设有一种简单的方法可以做到这一点,因为将复选框绑定到一个集合似乎是一件很自然的事情,但到目前为止我看到的所有解决方案似乎都过于复杂(例如:http://merill. net/2009/10/wpf-checked-listbox/)。

我通过修改 a 的数据模板ListBox并将 的 设置为ItemsSourceListBox创建复选框ObservableCollection,但我的问题是我不知道要绑定IsChecked到什么,因为我试图将它绑定到集合中的实际对象而不是对象的属性。

4

3 回答 3

5

用于IsChecked="{Binding}"直接绑定集合的项。

<ListBox ItemsSource="{Binding MyBooleanCollection}" >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox IsChecked="{Binding Mode=OneWay}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

但是,无法使用此方法绑定到源。因为对IsChecked属性的绑定CheckBox不是绑定项的索引。因此,它不能更改集合,而只能更改集合的项目。

更新

为了解决这个限制,您可以为布尔值创建一个包装器:

public class Wrapper<T> : INotifyPropertyChanged
{
    private T value;
    public T Value
    {
        get { return value; }
        set
        {
            {
                this.value = value;
                OnPropertyChanged();
            }
        }
    }

    public static implicit operator Wrapper<T>(T value)
    {
        return new Wrapper<T> { value = value };
    }
    public static implicit operator T(Wrapper<T> wrapper)
    {
        return wrapper.value;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

这是一个使用示例:

public partial class MainWindow : Window
{
    public ObservableCollection<Wrapper<bool>> MyBooleanCollection { get; private set; }

    public MainWindow()
    {
        InitializeComponent();

        DataContext = this;
        MyBooleanCollection = new ObservableCollection<Wrapper<bool>>() { false, true, true, false, true };
    }
}

在 XAML 中:

<CheckBox IsChecked="{Binding Value}"/>
于 2013-07-23T12:37:29.437 回答
4

ItemTemplate你可以写

<CheckBox IsChecked="{Binding Path=.}"/>

或者

<CheckBox IsChecked="{Binding Mode=OwnWay}"/>

它直接绑定到项目对象,即bool集合中的值。


但是请注意,在任何一种情况下,当 CheckBox 被选中或未选中时,集合中的绑定值都不会被替换。为了在单击 CheckBox 时立即更新集合,您的集合必须包含IsChecked绑定了布尔属性的对象。

在您的情况下,这可能很简单(因为您的问题听起来像您不需要属性更改通知):

public class BooleanHelper
{
    public bool Value { get; set; }
}

绑定现在看起来像这样:

<CheckBox IsChecked="{Binding Path=Value}"/>

该集合现在将是一个ObservableCollection<BooleanHelper>,您可能会添加这样的项目:

Items.Add(new BooleanHelper { Value = true });
于 2013-07-23T12:24:13.260 回答
0

通过您提供的链接,您还可以对 CheckedListItem 类使用 INotifyPropertyChanged 扩展,但前提是您不想使用 ObservableCollection。它会是这样的:

public class CheckedListItem : INotifyPropertyChanged
{
    private int _Id;
    public int Id 
    {
        get;
        set; NotifyIfAnythingChanged("Id");
    }

    private string _Name;
    public string Name
    {
        get;
        set; NotifyIfAnythingChanged("Name");
    }

    private bool _IsChecked;
    public bool IsChecked
    {
        get;
        set; NotifyIfAnythingChanged("IsChecked");
    }

    private void NotifyIfAnythingChanged(String propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

你的列表框应该是这样的:

<ListBox x:Name="MyListBox">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content={Binding Path=Name} IsChecked="{Binding Mode=TwoWay, Path=IsChecked}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

在你后面的代码中,你应该只初始化一次 ObservableCollection,因为对它所做的每一次更改都会导致 UI 更新。

ObservableCollection<CheckedListItem> MyList = new ObservableCollection<CheckedListItem>();
MyListBox.ItemsSource = MyList;

现在对 MyList 所做的每一项更改,例如 Add()、Remove() 等都会影响您的 UI。

于 2013-07-23T12:54:58.937 回答