繁体   English   中英

如何将对象的布尔属性绑定到CheckBox的IsChecked属性?

[英]How to bind an object's boolean property to a CheckBox's IsChecked property?

我有一个具有布尔属性的对象的ObservableCollection。

在GUI中,我有一个CheckBox,我想从中将其IsChecked属性绑定到每个对象的boolean属性。

仅可以使用XAML吗? 怎么样?

我只想用绑定来做,因为出价比循环快

尝试这个:

<ListBox ItemsSource={Binding path}>
  <ListBox.ItemTemplate>
    <DataTemplate>
      <CheckBox IsChecked="{Binding yourBoolPropertyName, Mode = TwoWay}" />
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

这将创建绑定到您的收藏夹的复选框列表。 当然,您必须正确设置绑定路径。

在ViewModel上创建一个bool属性,该属性将遍历ObservableCollection的所有Objects ,以查看每个对象的true属性-

public bool AllTrue
{
   get
   {
      return Objects.All(o => o.Selected);
   }
}

这里的ObjectsObservableCollection实例,而Selected是对象中的bool属性。

XAML

<CheckBox IsChecked="{Binding AllTrue}"/>

我创建了一个行为,以允许控件中的属性以以下方式绑定到项目集合的属性:

  • 如果您更改控件中的属性,则所有项目都会更新。
  • 如果更改项目中的属性,则如果所有项目都具有相同的属性,则控件将反映该属性。 如果不是,则控件的属性将被赋予后备值(如null)。

     public class CollectionPropertyBehavior : Behavior<DependencyObject> { private IEnumerable<ValueProxy> proxies; private bool syncking; public string SourcePropertyPath { get { return (string)GetValue(SourcePropertyPathProperty); } set { SetValue(SourcePropertyPathProperty, value); } } public static readonly DependencyProperty SourcePropertyPathProperty = DependencyProperty.Register("SourcePropertyPath", typeof(string), typeof(CollectionPropertyBehavior), new PropertyMetadata(null)); public string CollectionPropertyPath { get { return (string)GetValue(CollectionPropertyPathProperty); } set { SetValue(CollectionPropertyPathProperty, value); } } public static readonly DependencyProperty CollectionPropertyPathProperty = DependencyProperty.Register("CollectionPropertyPath", typeof(string), typeof(CollectionPropertyBehavior), new PropertyMetadata(null)); private IEnumerable<object> Items { get { return this.ItemsSource == null ? null : this.ItemsSource.OfType<object>(); } } public IEnumerable ItemsSource { get { return (IEnumerable)GetValue(ItemsSourceProperty); } set { SetValue(ItemsSourceProperty, value); } } public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CollectionPropertyBehavior), new PropertyMetadata(null, ItemsSourceChanged)); private object Value { get { return (object)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } private static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(CollectionPropertyBehavior), new PropertyMetadata(null, ValueChanged)); public object DefaultValue { get { return (object)GetValue(DefaultValueProperty); } set { SetValue(DefaultValueProperty, value); } } public static readonly DependencyProperty DefaultValueProperty = DependencyProperty.Register("DefaultValue", typeof(object), typeof(CollectionPropertyBehavior), new PropertyMetadata(null)); private static void ValueChanged(object sender, DependencyPropertyChangedEventArgs args) { var element = sender as CollectionPropertyBehavior; if (element == null || element.ItemsSource == null) return; element.UpdateCollection(); } private static void ItemsSourceChanged(object sender, DependencyPropertyChangedEventArgs args) { var element = sender as CollectionPropertyBehavior; if (element == null || element.ItemsSource == null) return; element.ItemsSourceChanged(); } private void ItemsSourceChanged() { this.proxies = null; if (this.Items == null || !this.Items.Any() || this.CollectionPropertyPath == null) return; // Cria os proxies this.proxies = this.Items.Select(o => { var proxy = new ValueProxy(); proxy.Bind(o, this.CollectionPropertyPath); proxy.ValueChanged += (s, e) => this.UpdateSource(); return proxy; }).ToArray(); this.UpdateSource(); } private void UpdateSource() { if (this.syncking) return; // Atualiza o valor using (new SynckingScope(this)) { object value = this.proxies.First().Value; foreach (var proxy in this.proxies.Skip(1)) { value = object.Equals(proxy.Value, value) ? value : this.DefaultValue; } this.Value = value; } } private void UpdateCollection() { // Se o valor estiver mudando em função da atualização de algum // elemento da coleção, não faz nada if (this.syncking) return; using (new SynckingScope(this)) { // Atualiza todos os elementos da coleção, // atrávés dos proxies if (this.proxies != null) foreach (var proxy in this.proxies) proxy.Value = this.Value; } } protected override void OnAttached() { base.OnAttached(); // Bind da propriedade do objeto fonte para o behavior var binding = new Binding(this.SourcePropertyPath); binding.Source = this.AssociatedObject; binding.Mode = BindingMode.TwoWay; BindingOperations.SetBinding(this, ValueProperty, binding); } protected override void OnDetaching() { base.OnDetaching(); // Limpa o binding de value para a propriedade do objeto associado this.ClearValue(ValueProperty); } internal class SynckingScope : IDisposable { private readonly CollectionPropertyBehavior parent; public SynckingScope(CollectionPropertyBehavior parent) { this.parent = parent; this.parent.syncking = true; } public void Dispose() { this.parent.syncking = false; } } internal class ValueProxy : DependencyObject { public event EventHandler ValueChanged; public object Value { get { return (object)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(ValueProxy), new PropertyMetadata(null, OnValueChanged)); private static void OnValueChanged(object sender, DependencyPropertyChangedEventArgs args) { var element = sender as ValueProxy; if (element == null || element.ValueChanged == null) return; element.ValueChanged(element, EventArgs.Empty); } public void Bind(object source, string path) { // Realiza o binding de value com o objeto desejado var binding = new Binding(path); binding.Source = source; binding.Mode = BindingMode.TwoWay; BindingOperations.SetBinding(this, ValueProperty, binding); } } } 

您可以像这样使用它:

<CheckBox>
    <i:Interaction.Behaviors>
        <local:CollectionPropertyBehavior CollectionPropertyPath="MyBooleanProperty" SourcePropertyPath="IsChecked" ItemsSource="{Binding CollectionInViewModel}"/>
    </i:Interaction.Behaviors>
</CheckBox>

它尚不支持集合更改(仅集合交换),但是我相信可以很容易地对其进行修改。 如果要立即使用它,则可以将处理程序添加到ObservableCollection的CollectionChanged事件中,这样它将触发ItemsSource更新:

observableCollection.CollectionChanged += (s,e) => this.OnPropertyChanged("ItemsSource);

我在这里发布了另一个示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM