Solved

StringCollection Set Property Not Firing Correctly

Posted on 2010-08-12
11
570 Views
Last Modified: 2013-12-17
private System.Collections.Specialized.StringCollection _Names;
        [Editor("System.Windows.Forms.Design.StringCollectionEditor,System.Design,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public StringCollection Names
        {
            get
            {
                return _Names;
            }
            set
            {
                _Names = value;
                foreach (string Name in _Names)
                {
                    System.Diagnostics.Debug.WriteLine("Table Control: Tag: " + Name);
                }
          }
        }

I could change the values inside the Names property via the property grid. But it does not print anything to the OUTPUT windows. What am I doing wrong here??
0
Comment
Question by:YetAnotherCoder
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 3
11 Comments
 
LVL 16

Expert Comment

by:kris_per
ID: 33424912

See what happens if you use 'MessageBox' instead of 'WriteLine'....
0
 

Author Comment

by:YetAnotherCoder
ID: 33426729
The set property is not executing.....at all
0
 
LVL 3

Expert Comment

by:yanoch
ID: 33429460
You should initiate the string collection before setting a value.

the set of the property is just fired if you add a new string collection to _Names.
     Names = new StringCollection(); // It fire the set

In your case, your are modifying the current string collection (Current value of _Names) and using the get of the property.
 
you should write your code like that :

 private System.Collections.Specialized.StringCollection _Names = new StringCollection();
        [Editor("System.Windows.Forms.Design.StringCollectionEditor,System.Design,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public StringCollection Names
        {
            get
            {
                 //fired when accessing the _Names value
                 //In your case when you modify it.
                return _Names;
            }
            set
            {
                //fired when setting the _Names  value

                _Names = value;
                foreach (string Name in _Names)
                {
                    System.Diagnostics.Debug.WriteLine("Table Control: Tag: " + Name);
                }
        }
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:YetAnotherCoder
ID: 33430220
Hi Yanoch,
It is not firing when I modify the collection via the CollectionEditor in the design mode. Have you verified it??? What have you modified to my code.... I couldn't follow if you have made any changes other than the comments.....
0
 
LVL 3

Expert Comment

by:yanoch
ID: 33430439
added
private System.Collections.Specialized.StringCollection _Names = new StringCollection();

No it is not fireing because you are only modifying the current instance of _Names, you are not adding a new value to it.

if you do : _Names = something it will fire the set.

In your case the property editor modify the content of _Names it does not set a someting to _Names.

The property editor does not create a new instance of _Names, it is only modifying it.
0
 

Author Comment

by:YetAnotherCoder
ID: 33430903
Is there a work around for this?? or a better way to do this... Please need some help
0
 
LVL 16

Expert Comment

by:kris_per
ID: 33431053

@YetAnotherCoder

As yanoch has posted, set property is not executed because it is not called or not used by the designer at all...

When you add items to the Names property in the designer editor, it adds the new items to the already existing Names list (like Names.Add) and it is not setting any new value to Names property. i.e. Names set is not called at all...

Names set will be called when you do something like below:

public Form1()
{
        InitializeComponent();

        myControl.Names = new new System.Collections.Specialized.StringCollection(); // Now Names set will be called

         myControl.Names.Add("item1"); // Here Names set will not be called. Designer/Editor is doing this..

}

So i think you dont need any workaround...that's the way it is....hope this helps...


0
 

Author Comment

by:YetAnotherCoder
ID: 33431201
Hey Kris,

But I using the above mentioned property in a UserControl where users would like to make changes in the PropertyGrid. They wont have access to the code.... Similar to Comobo Box Items Collection, I would like to provide my control a Names property that lets them make changes to the list as they wish..... As they make changes in the designer, I would like to know so that I could update other properties that depend on Names Collection property.

So how could I get changes notifications when made to this property in the designer itself?? Or is there a workaround for this??

Thank You
0
 
LVL 3

Accepted Solution

by:
yanoch earned 250 total points
ID: 33431262
If you want to have an event when the property is changin you have to write your own collection class

here's an example.

You have all the events needed

using System;
using System.Collections;
using System.Collections.Generic;

namespace SmartControls.Types
{
    public class ItemChangedArgs<T> : EventArgs
    {
        public int Index { get; set; }
        public T Item { get; set; }
    }

    public class EventList<T> : CollectionBase
    {
        public event EventHandler<ItemChangedArgs<T>> ItemAdded;
        public event EventHandler<ItemChangedArgs<T>> ItemRemoved;
        public event EventHandler<ItemChangedArgs<T>> ItemChanged;
        public event EventHandler Cleared;

        public void Add(T item)
        {
            this.List.Add(item);
        }

        public void AddRange(IEnumerable<T> collection)
        {
            foreach (T t in collection)
            {
                this.List.Add(t);
            }
        }

        private void OnItemAdded(int index, T item)
        {
            if (ItemAdded != null)
                ItemAdded(this, new ItemChangedArgs<T> { Index = index, Item = item });
        }

        public int IndexOf(T item)
        {
            return this.List.IndexOf(item);
        }

        public void Insert(int index, T item)
        {
            this.List.Insert(index, item);
            OnItemAdded(index, item);
        }

        protected override void OnRemoveComplete(int index, object value)
        {
            OnRemove(index, (T)value);
            base.OnRemoveComplete(index, value);
        }

        protected override void OnClearComplete()
        {
            OnCleared();
            base.OnClearComplete();
        }

        protected override void OnSetComplete(int index, object oldValue, object newValue)
        {
            OnItemChanged(index, (T)newValue);
            base.OnSetComplete(index, oldValue, newValue);
        }

        protected override void OnInsertComplete(int index, object value)
        {
            OnItemAdded(index, (T)value);
            base.OnInsertComplete(index, value);
        }
        
        private void OnItemRemoved(int index, T item)
        {
            if (ItemRemoved != null)
                ItemRemoved(this, new ItemChangedArgs<T> { Index = index, Item = item });
        }

        public T this[int index]
        {
            get 
            {
                return (T)this.List[index]; 
            }
            set
            {
                this.List[index] = value;
                OnItemChanged(index, (T)this.List[index]);
            }
        }

        private void OnItemChanged(int index, T item)
        {
            if (ItemChanged != null)
                ItemChanged(this, new ItemChangedArgs<T> { Index = index, Item = item });
        }

        private void OnCleared()
        {
            if (Cleared != null) 
                Cleared(this, null);
        }

        public bool Contains(T item)
        {
            return this.List.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            this.List.CopyTo(array, arrayIndex);
        }

        public void Remove(T item)
        {
            this.List.Remove(item);
        }
    } 

}

Open in new window

0
 
LVL 16

Assisted Solution

by:kris_per
kris_per earned 250 total points
ID: 33432091

I have tired yanoch's code. It is working good and hope that's what you want...you have to use it like as shown below:
public partial class UserControl5 : UserControl
    {
        public UserControl5()
        {
            InitializeComponent();

            _Names.ItemAdded += new EventHandler<ItemChangedArgs<string>>(_Names_ItemAdded);
        }

        void _Names_ItemAdded(object sender, ItemChangedArgs<string> e)
        {
            // this method will be called whenever item is added to _Names
        }

        private EventList<string> _Names = new EventList<string>();

        [Editor("System.Windows.Forms.Design.StringCollectionEditor,System.Design,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public EventList<string> Names
        {
            get
            {
                 //fired when accessing the _Names value 
                 //In your case when you modify it.
                return _Names;
            }
            set
            {
                //fired when setting the _Names  value

                _Names = value;
                foreach (string Name in _Names)
                {
                    System.Diagnostics.Debug.WriteLine("Table Control: Tag: " + Name);
                }
            }
        }
}

Open in new window

0
 

Author Closing Comment

by:YetAnotherCoder
ID: 33433287
Thank you Yanoch the class and Kris_per for showing the usage... Apreciate both your help......Very nice.....
0

Featured Post

Business Impact of IT Communications

What are the business impacts of how well businesses communicate during an IT incident? Targeting, speed, and transparency all matter. Find out more in this infographic.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
How to Install VMware Tools in Red Hat Enterprise Linux 6.4 (RHEL 6.4) Step-by-Step Tutorial

732 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question