将值从一个类绑定到另一个类中的另一个值

时间:2014-03-02 13:11:22

标签: c# wpf binding

我有以下课程gist with the classes 我想将Item.Visible绑定到Items.ItemsVisible - 它可能吗?,如果是这样 - 怎么样?

Item.cs:

using System;
using System.ComponentModel;

namespace WpfApplication85
{
    /// <summary>
    /// Item Object.
    /// </summary>
    public class Item : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged; //Event to notify when Property changed.

        /// <summary>
        /// Notify that Property has Changed.
        /// </summary>
        /// <param name="propertyName">The name of the Property</param>
        protected void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region Private Variables

        private bool _Visible; //Bool to determine if the Item is visible or not

        #endregion

        #region Public Properties

        //Return the value of Visible / Set the value of Visible and Notify.
        public bool Visible 
        {
            get { return _Visible; }
            set 
            { 
                _Visible = value;
                NotifyPropertyChanged("Visible");
            }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Item Constructor
        /// </summary>
        public Item()
        {
            _Visible = true;
        }

        #endregion
    }
}

Items.cs:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WpfApplication85
{
    /// <summary>
    /// Items Object.
    /// </summary>
    public class Items : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged; //Event to notify when Property changed.

        /// <summary>
        /// Notify that Property has Changed.
        /// </summary>
        /// <param name="propertyName">The name of the Property</param>
        protected void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region Private Variables

        private bool _itemsVisible; //Bool to determine if the Items are visible or not
        private ObservableCollection<Item> _itemsCollection; //Collection of Items.

        #endregion

        #region Public Properties

        //Return the value of ItemsVisible / Set the value of ItemsVisible and Notify.
        public bool ItemsVisible
        {
            get { return _itemsVisible; }
            set 
            { 
                _itemsVisible = value;
                NotifyPropertyChanged("ItemsVisible");
            }
        }

        //Return the Items Collection / Set the Items Collection and Notify.
        public ObservableCollection<Item> ItemsCollection
        {
            get
            {
                return _itemsCollection;
            }
            set
            {
                _itemsCollection = value;
                NotifyPropertyChanged("ItemsCollection");
            }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Items Constructor
        /// </summary>
        public Items()
        {
            _itemsVisible = true;
            _itemsCollection = new ObservableCollection<Item>();
        }

        #endregion

        #region Methods

        /// <summary>
        /// Add Item to the ItemsCollection.
        /// </summary>
        /// <param name="item">Item Object</param>
        public void AddItem(Item item)
        {
            //Bind item.Visible to this.ItemsVisible
            _itemsCollection.Add(item);
        }

        #endregion
    }
}

2 个答案:

答案 0 :(得分:2)

ItemsItem属性中设置数据绑定只不过是从正确的接口监听PropertyChangedCollectionChanged事件。

您可以使用+=子句进行订阅,也可以WeakEventListener模式使用PropertyChangedEventManagerCollectionChangedEventManager

我更喜欢最后一个,因为:

  

侦听事件可能会导致内存泄漏。

因此,您的Items类应该实现IWeakEventListener接口:

public class Items : INotifyPropertyChanged, IWeakEventListener
{
    #region IWeakEventListener

    public bool ReceiveWeakEvent(Type managerType, Object sender, EventArgs e)
    {
        if (sender == this._itemsCollection && managerType == typeof(CollectionChangedEventManager))
        {
            // Your collection has changed, you should add/remove
            // subscription for PropertyChanged event
            UpdateSubscriptions((NotifyCollectionChangedEventArgs)e);
            return true;
        }
        if (sender is Item && managerType == typeof(PropertyChangedEventManager))
        {
            // The Visible property of an Item object has changed
            // You should handle it properly here, for example, like this:
            this.ItemsVisible = this._itemsCollection.All(i => i.Visible);
            return true;
        }

        return false;
    }

    private void UpdateSubscriptions(NotifyCollectionChangedEventArgs e)
    {
        switch(e.Action)
        {
            case NotifyCollectionChangedAction.Add:
                foreach (Item item in e.NewItems)
                {
                    PropertyChangedEventManager.AddListener(item, this, "Visible");
                }
                break;
            case NotifyCollectionChangedAction.Remove:
                foreach (Item item in e.OldItems)
                {
                    PropertyChangedEventManager.RemoveListener(item, this, "Visible");
                }
                break;
            case NotifyCollectionChangedAction.Reset:
                foreach (Item item in this._itemsCollection)
                {
                    PropertyChangedEventManager.RemoveListener(item, this, "Visible");
                    PropertyChangedEventManager.AddListener(item, this, "Visible");
                }
                break;
             default:
                break;
        }
    }

...
    public Items()
    {
        _itemsVisible = true;
        _itemsCollection = new ObservableCollection<Item>();
        CollectionChangedEventManager.AddListener(_itemsCollection, this);
    }
}

答案 1 :(得分:0)

WPF意义上的绑定仅适用于DependencyProperties,并且不适用于两个标准属性(即使使用INotifyPropertyChanged时)。

也就是说,如果您将这些类用作View Models并将它们绑定到控件,则可以使用MultiConverter将ItemsVisible和Visible属性都为true时控件的可见性设置为折叠(例如)。 / p>

或者,您可以将一个Parent属性添加到Item类并将其设置为父Items类,这将允许您让Item.Visible属性返回父项的ItemsVisible属性(或者再次在您的应用程序中有意义的逻辑)