2

ブール値のプロパティを持つオブジェクトの ObservableCollection があります。

GUI には、IsChecked プロパティを各オブジェクトのブール プロパティにバインドする CheckBox があります。

XAML のみを使用することは可能ですか? どのように?

束縛だけでやりたい ループより入札の方が早い

4

3 に答える 3

6

これを試して:

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

これにより、コレクションにバインドするチェックボックスのリストが作成されます。もちろん、バインディング用のパスを適切に設定する必要があります。

于 2012-11-27T18:42:00.000 に答える
0

ViewModelにboolプロパティを作成します。これは、すべてObjectsのObservableCollectionをループして、すべてのオブジェクトに対してプロパティがtrueであることを確認します。

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

これがあなたObjectsのインスタンスでありObservableCollectionSelectedオブジェクトのboolプロパティです。

XAML

<CheckBox IsChecked="{Binding AllTrue}"/>
于 2012-11-27T19:01:11.140 に答える
0

次のような方法で、コントロール内のプロパティを項目のコレクションのプロパティにバインドできるようにする動作を作成しました。

  • コントロールのプロパティを変更すると、すべての項目が更新されます。
  • アイテムのプロパティを変更すると、すべてのアイテムが同じプロパティを持つ場合、コントロールに反映されます。そうでない場合、コントロールのプロパティにはフォールバック値 (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);

ここに別の例を投稿しました。

于 2012-11-27T19:13:01.040 に答える