让我通过声明我对C#和WPF都很陌生来为这个问题添加前缀。
我正在尝试将Boolean
值集合连接到包含6个复选框的容器,并在按下按钮时存储这些值的状态。我假设有一种简单的方法可以做到这一点,因为绑定到一个集合的复选框似乎是很自然的事情,但到目前为止我看到的所有解决方案似乎都过于复杂(例如:http://merill.net/2009/10/wpf-checked-listbox/) 。
我通过修改ListBox
的数据模板来创建复选框,并将ItemsSource
的{{1}}设置为ListBox
,但问题是我不知道知道要绑定ObservableCollection
的内容,因为我试图将它绑定到集合中的实际对象而不是对象的属性。
答案 0 :(得分:5)
使用IsChecked="{Binding}"
直接绑定集合的项目。
<ListBox ItemsSource="{Binding MyBooleanCollection}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Mode=OneWay}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
但是,使用此方法无法绑定到源。因为IsChecked
的{{1}}属性上的绑定不是绑定项的索引。因此,它不能更改集合,只能更改集合的项目。
要解决该限制,您可以创建布尔值的包装器:
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));
}
}
在XAML中:
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 };
}
}
答案 1 :(得分:4)
在ItemTemplate
你可以写
<CheckBox IsChecked="{Binding Path=.}"/>
或
<CheckBox IsChecked="{Binding Mode=OwnWay}"/>
直接绑定到item对象,即集合中的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 });
答案 2 :(得分: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()等等都会影响你的用户界面。