简体   繁体   English

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

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

I have an ObservableCollection of objects that have a boolean property. 我有一个具有布尔属性的对象的ObservableCollection。

In the GUI, I have a CheckBox from which I want to bind its IsChecked property to each object's boolean property. 在GUI中,我有一个CheckBox,我想从中将其IsChecked属性绑定到每个对象的boolean属性。

Is it possible using XAML only? 仅可以使用XAML吗? How? 怎么样?

I want to do it only with binding cause biding is faster than loop 我只想用绑定来做,因为出价比循环快

Try this: 尝试这个:

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

This will create list of checkboxes that will bind to your collection. 这将创建绑定到您的收藏夹的复选框列表。 Of course, you must properly set paths for binding. 当然,您必须正确设置绑定路径。

Create a bool property on your ViewModel which will loop through all Objects of your ObservableCollection to see property is true for every object - 在ViewModel上创建一个bool属性,该属性将遍历ObservableCollection的所有Objects ,以查看每个对象的true属性-

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

Here Objects is instance of your ObservableCollection and Selected is a bool property in an object. 这里的ObjectsObservableCollection实例,而Selected是对象中的bool属性。

XAML XAML

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

I have created a behavior to allow a property in a control to be bound to a property of a collection of items, in a way that: 我创建了一个行为,以允许控件中的属性以以下方式绑定到项目集合的属性:

  • If you change the property in the control, all of the items are updated. 如果您更改控件中的属性,则所有项目都会更新。
  • If you change the property in a item, if all the items have the same property the control will reflect it. 如果更改项目中的属性,则如果所有项目都具有相同的属性,则控件将反映该属性。 If not, the property of the control will be given a fallback value (like null). 如果不是,则控件的属性将被赋予后备值(如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); } } } 

You can use it like this: 您可以像这样使用它:

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

It doesn't support collection changes yet (just collection swap), but I believe it can be easily modified to to that. 它尚不支持集合更改(仅集合交换),但是我相信可以很容易地对其进行修改。 If you want to use it out of the box, you can just add a handler to the CollectionChanged event of your ObservableCollection so it will trigger the ItemsSource update: 如果要立即使用它,则可以将处理程序添加到ObservableCollection的CollectionChanged事件中,这样它将触发ItemsSource更新:

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

I've posted another example here . 我在这里发布了另一个示例。

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

相关问题 如何将 WPF 复选框的 IsChecked 属性绑定到非窗口对象的布尔属性 - How can I bind a WPF checkbox's IsChecked property to a boolean property of an object that is not a window 在WPF中,如何将Checkbox的IsChecked绑定到List &lt;&gt;。Contains? - In WPF, how do I two-way bind a Checkbox's IsChecked to property to List<>.Contains? 如何将两个东西绑定到复选框的 IsChecked 属性? - How to bind two things to IsChecked property of checkbox? 如何将ItemTemplate CheckBox的Command属性绑定到ViewModel对象的属性? - How to bind the Command property of the ItemTemplate CheckBox to ViewModel object's property? 为什么在WPF CheckBox中IsChecked属性为可空布尔值? - Why is IsChecked property nullable boolean in WPF CheckBox? 如何将另一个DependencyProperty绑定到CheckBox的IsChecked属性? - How can I bind another DependencyProperty to the IsChecked Property of a CheckBox? 如何在ItemsControl中绑定CheckBox的IsChecked属性? - How do I bind IsChecked property of CheckBox within an ItemsControl? 将ToggleButton IsChecked属性绑定到RichTextBox的附加行为的语法 - Syntax to bind a ToggleButton IsChecked property to a RichTextBox's attached behavior 将按钮的IsEnabled属性绑定到XAML中的2个复选框IsChecked属性 - Binding a button's IsEnabled property to 2 checkbox IsChecked properties in XAML 如何绑定菜单项的IsChecked属性 - How to Bind IsChecked Property of Menu item
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM