【问题标题】:Bind value from one class to another value in another class将一个类中的值绑定到另一个类中的另一个值
【发布时间】:2014-03-02 13:11:22
【问题描述】:

我有以下课程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
    }
}

【问题讨论】:

  • Items 是 Item 的成员。所以当 Items.ItemsVisible 属性值发生变化时。您可以遍历集合中的每个项目并设置相同的值。
  • 我知道我可以循环...我正在尝试找到“更好”的方式然后循环,这就是为什么我想知道是否可以绑定它们
  • 你将如何从集合中获取真/假或可见/不可见?
  • 为什么我需要从集合中获取真/假?作为 Items 类的属性的 ItemsVisible 属性持有真/假

标签: c# wpf binding


【解决方案1】:

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);
    }
}

【讨论】:

  • 我理解你的方法,当我在寻找更简单的解决方案然后遍历我的项目时,你提供了更复杂的东西(使用监听器) - 我认为它更复杂?
  • 我只是向您展示了完成属性更新的另一种可能性,并解释了为什么您应该尝试这种方法。如果在某些 Item.Visible 发生更改时需要更改 ItemsVisible,则这是必需的。如果您只需要更改 Item.Visible 属性,则只需在 ItemsVisible 设置器中进行即可。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2022-11-21
    • 2011-08-26
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    相关资源
    最近更新 更多