簡體   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