Solved

User Control Properties

Posted on 2004-04-13
27
662 Views
Last Modified: 2008-01-16
Hello everyone,

I am having a problem with a user control.  In my application I create a user control that inherits from a listview control.  I basically turn a listview control into an appointments list with a few columns.  Sort of like a template.  Everything works fine to a certain point.  I can add the control to my forms and everything displays okay.  When I try to override certain properties such as the column widths, every time I compile they return back to the default width.  I tried setting the property in the user control to public instead of private and it still does not work.  I am trying to do this at design time.  Are there any suggestions out there?????  Another thing is that in this user control I list time slots (8:00, 8:20, 8:40, 9:00, etc.)  all the way to 5:00.  For some reason I can leave the form to work on another form and when I come back to it, I have two sets of items back to back.  Running 8-5 and another set right after that.  All of this happens at design time.  Any suggestions????????????????????  Please Help.........

Thanks,
Kendal
0
Comment
Question by:gvector1
  • 11
  • 10
  • 4
  • +2
27 Comments
 
LVL 8

Expert Comment

by:RomanPetrenko
ID: 10816941
can you post here your code?
0
 
LVL 20

Accepted Solution

by:
TheAvenger earned 167 total points
ID: 10817093
Unfortunately the designer makes some problems with some design time properties. I suggest that you set the properties at run time, e.g. in the OnLoad event.

For the two sets of hours: you probably add the items in an event that is executed twice in your scenario, e.g. the VisibleChanged event. Note that the designer actually executes the control during design time so it will also call events like OnLoad, etc.
0
 

Author Comment

by:gvector1
ID: 10817255
It is quite a bit of code, but here is some of it:

[code]
      public class ApptsListView : System.Windows.Forms.ListView
      {
            public System.Windows.Forms.ColumnHeader Time;
            public System.Windows.Forms.ColumnHeader ChartNum;
            public System.Windows.Forms.ColumnHeader Patient;
            public System.Windows.Forms.ColumnHeader Status;
            public System.Windows.Forms.ColumnHeader Room;
            public System.Windows.Forms.ColumnHeader InTime;
            public System.Windows.Forms.ColumnHeader WaitTime;
            
                                private void InitializeComponent()
            {
            System.Windows.Forms.ListViewItem listViewItem1 =
                                   new System.Windows.Forms.ListViewItem(
                                   new System.Windows.Forms.ListViewItem.ListViewSubItem[] {
                                   new System.Windows.Forms.ListViewItem.ListViewSubItem
                                             (null, "8:00    A.M.",
                                              System.Drawing.SystemColors.WindowText,
                                              System.Drawing.SystemColors.Window,
                                              new System.Drawing.Font("Verdana", 6.75F,
                                                     System.Drawing.FontStyle.Regular,
                                                     System.Drawing.GraphicsUnit.Point,
                                                     ((System.Byte)(0)))),
                                  new System.Windows.Forms.ListViewItem.ListViewSubItem
                                             (null, "",
                                              System.Drawing.SystemColors.WindowText,
                                              System.Drawing.SystemColors.Window,
                                              new System.Drawing.Font("Verdana", 6.75F,
                                                     System.Drawing.FontStyle.Regular,
                                                     System.Drawing.GraphicsUnit.Point,
                                                     ((System.Byte)(0)))),
             new System.Windows.Forms.ListViewItem.ListViewSubItem
                                            (null, ""),
                                 new System.Windows.Forms.ListViewItem.ListViewSubItem
                                            (null, ""),
             new System.Windows.Forms.ListViewItem.ListViewSubItem
                                            (null, ""),
                                 new System.Windows.Forms.ListViewItem.ListViewSubItem
                                            (null, ""),
             new System.Windows.Forms.ListViewItem.ListViewSubItem
                                            (null, "")}, -1);
            System.Windows.Forms.ListViewItem listViewItem2 =
                                   new System.Windows.Forms.ListViewItem(new string[]
                                            { "     :20","","","","","",""}, -1);
            System.Windows.Forms.ListViewItem listViewItem3 =
                                   new System.Windows.Forms.ListViewItem(new string[]
                                            {"     :40","","","","","",""}, -1);
............................................ETC.

            this.Time = new System.Windows.Forms.ColumnHeader();
            this.Status = new System.Windows.Forms.ColumnHeader();
            this.ChartNum = new System.Windows.Forms.ColumnHeader();
            this.Patient = new System.Windows.Forms.ColumnHeader();
            this.Room = new System.Windows.Forms.ColumnHeader();
            this.InTime = new System.Windows.Forms.ColumnHeader();
            this.WaitTime = new System.Windows.Forms.ColumnHeader();
            //
            // Time
            //
            this.Time.Text = "Time";
            this.Time.Width = 70;
            //
            // Status
            //
            this.Status.Text = "Status";
            this.Status.Width = 80;
            //
            // ChartNum
            //
            this.ChartNum.Text = "Chart";
            //
            // Patient
            //
            this.Patient.Text = "Patient";
            this.Patient.Width = 150;
            //
            // Room
            //
            this.Room.Text = "Room";
            //
            // InTime
            //
            this.InTime.Text = "In";
            this.InTime.Width = 67;
            //
            // WaitTime
            //
            this.WaitTime.Text = "Wait";
            //
            // ApptsListView
            //
            this.Columns.AddRange(new
                                   System.Windows.Forms.ColumnHeader[] {
                                      this.Time,
                  this.Status,
                  this.ChartNum,
                  this.Patient,
                  this.Room,
                  this.InTime,
                  this.WaitTime});
                    this.Items.AddRange(new System.Windows.Forms.ListViewItem[]{
                                      listViewItem1,
                  listViewItem2,
                  listViewItem3,
                  listViewItem4,
                  listViewItem5,
                  listViewItem6,
                  listViewItem7,
                  listViewItem8,
                  etc.....................................)                  

[/code]

That is most of the relevant code for the user control.  I then add the control to the form.  All of the columns and items are visible on the form.  I have tried to go through the columns property to set the column widths and tried dragging the dividers in the control during design time to set the column widths.  It works and the widths are adjusted until the program is built.  Once built, the widths revert back to the origional numbers.  Any suggestions?????????????????????

Thanks,
Kendal
0
 
LVL 4

Assisted Solution

by:caner_elci
caner_elci earned 167 total points
ID: 10818781
When you resize a column in design view, VS won't add the needed code to InitializeComponent() of your form.. Because columns are a collection of your inherited ListView.. So when you change the size of a column, designer tries to add a code for it and it messed up things (mine adds some more list items).. You should add resize code manually, but not in InitializeComponent of your form, because it won't be able to process it and give you an error. The only place to put that code in is Form's OnLoad event as others say..
0
 
LVL 1

Expert Comment

by:simion_tishler
ID: 10818842
Hi

I had the same problem with Backcolor and I got around it by renaming backcolor to ControlColor and using backcolor inside the usercontrol. Sorry but that is the only way I got around it.

Simion
0
 
LVL 4

Expert Comment

by:caner_elci
ID: 10818914
Hey, I think I did something good :)

Just try this:

Add your user control this property:

public new System.Windows.Forms.ListView.ColumnHeaderCollection Columns { get { return this.Columns; } set { this.Columns = value; } }

It worked.. when I set column widths in design view, now it keeps the changes after compilation...
0
 
LVL 4

Expert Comment

by:caner_elci
ID: 10818998
Opps, forgot my previous comment.. it was stupid :) Infinite call to Columns property.. but it worked and it's strange.. I think my VS messed up.. You'll probably get stack overflow exception when you try to create a control that has this property..
0
 
LVL 1

Expert Comment

by:simion_tishler
ID: 10819030
Yahooooo it worked. I've been trying to fix that for ages. It also fix an onther problem with overriding enabled. It always said I needed the new keyword but I tried and I must have put it in the wrong spot.

Cool thanks

Simion
0
 
LVL 4

Expert Comment

by:caner_elci
ID: 10819050
It did?? Are you sure?

By the way, I changed the property to:

public new System.Windows.Forms.ListView.ColumnHeaderCollection Columns {
      get { return base.Columns; }
      set {
            ListView.ColumnHeaderCollection c = ((ListView.ColumnHeaderCollection)value);
            base.Columns.Clear();
            foreach( ColumnHeader ch in c )
                  base.Columns.Add( ch );
      }
}

but it still doesn't work.. how come it works now?
0
 
LVL 1

Expert Comment

by:simion_tishler
ID: 10819075
hey caner_elci

try doing

base.Columns = value;

That fixed my problems with infinite loops
0
 
LVL 4

Expert Comment

by:caner_elci
ID: 10819099
I'm glad that worked.. I worked for me too once, but now it says base.Columns is read-only, that's I can't set it.. that's why I tried enumerating and adding manually.. strange.. Anyway, if it works, let it work, don't change anything :)
0
 
LVL 1

Expert Comment

by:simion_tishler
ID: 10819199
Yeah well

I don't have a deeper knowledge of what your doing but from what I can see maybe you should try the override keyword instead of new.

public override System.Windows.Forms.ListView.ColumnHeaderCollection Columns

Also I actually used fixed column names instead of providing an automatically extending listview.  Eg I only had two columns so I create two properties called columnwidth1 and columnwidth2 and created the columns inside the startup logic of the usercontrol. I know it's a bit lame but I didn't have time to stuff around with making things perfect. And I knew I would only ever use two columns.
0
 
LVL 4

Expert Comment

by:caner_elci
ID: 10820529
You cannot use override keyword there since Columns is not a overridable property of ListView.. The only way to hide it (not override), using new keyword.. Well, it's okay then.. it works for you, but what about gvector1?
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 1

Expert Comment

by:simion_tishler
ID: 10820648
well it seems to me that his problem is that he has the default values in the intialise code and maybe he should try the defaultvalue attribute instead.

[DefaultValue(false)]
 public bool MyProperty {
    get {
       return myVal;
    }
    set {
       myVal=value;
    }
 }

I don't use default values I just leave it empty and set it when I I'm setting up my usercontrol. This is what I have.

public int Columnwidth1
{
    get
    {
      return columnwidth1;
    }
    set
    {
      columnwidth1 = value;
      this.columnHeader1.Width = columnwidth1;
    }
}

I hope that helps
0
 
LVL 4

Expert Comment

by:caner_elci
ID: 10820679
It's okay, but designer needs to have some ColumnHeader objects to apply changes those made in inherited ListView class.. That's why we can't keep them stored in form's init... It can't find those objects, because they are hidden in inherited ListView class.. Making them public or any other similar changes won't work here..
0
 
LVL 1

Assisted Solution

by:simion_tishler
simion_tishler earned 166 total points
ID: 10820728
I was suggesting using my code and instead of his code in the intialise

 this.InTime.Text = "In";
          this.InTime.Width = 67;

use

 this.InTime.Text = InTimeText;
 this.InTime.Width = InTimeWidth;

InTimeWidth and InTimeText being public properties? I think thats what he wants.

Anyway I hope he bloody comes back too look as this thread because we have put lot of effort in and there no sign of him. Hahahaha
0
 
LVL 4

Expert Comment

by:caner_elci
ID: 10820940
Hell yeah! :) We better stop pretending and wait till he comes around :)
0
 

Author Comment

by:gvector1
ID: 10822975
Hello guys,

I greatly appreciate your efforts.  I am in a Central Standard Time Zone and was at home while you were all posting your replies.  I just got back to work and am checking out all of your recommendations.  Let me try a few and I will award the points accordingly.  I believe because both of you have put so much effort into this post I will split the points.  I wish I could double the points and award both of you the full point value.  Be back shortly.

Thanks,
Kendal
0
 

Author Comment

by:gvector1
ID: 10825209
Guys,
I greatly appreciate the replies to my problem.  They were extremely helpful.  I have run into some problems but for the meantime have gotten the problem solved by setting the column width at run time after the Initialization routine.  Just like you both were suggesting.  I will trial and error some more approaches later, but for the time being that will work and I gladly award you both the points.

Thanks Again,
Kendal
0
 

Author Comment

by:gvector1
ID: 10825330
Correction,

I believe it only fair that I split the points 3 ways.  I am actually using an approach that Avenger posted first.  Since caner and simion have posted some suggestions and code snippets that have helped me and I am still experimenting with, I will split the points as best I can 3 ways.

Thanks again,
Kendal
0
 
LVL 1

Expert Comment

by:simion_tishler
ID: 10828867
hey caner_elci

I just want to say that the new keyword with background didn't work. The problem is that the designer doesn't actually put any code for you in the intialising code after you have set the background. It show a color change in the designer but there is no code and when you run it and defaults to the default color. Also override didn't work either. There has to be a way around this. Hmmm

Any clues

Regards

Simion
0
 
LVL 4

Expert Comment

by:caner_elci
ID: 10830814
Hey Simion,

That's what I'm talking about.. I think our lovely form designer is not that clever about user controls.. It doesn't care too much about code generation... But as you say, there is way to make it generate code for it, and I've done it many times.. But I think the main problem is Collection properties.. Anyway, these hopefully be fixed in the next version of VS.NET, but for now, I'll check what have I done in that application, to make designer generate code for my user controls... I'll let you know...

Cheers,

Caner
0
 
LVL 1

Expert Comment

by:simion_tishler
ID: 10837881
Hey dude I worked it out but I not one hundred percent why.

This is what works and auto generates my code.

public override Color BackColor
            {
                  get
                  {
                        return base.BackColor;
                  }
                  set
                  {
                        base.BackColor = value;
                        this.textBox1.BackColor = base.BackColor;
                  }
            }

This is what didn't work. But the thing is that I didn't get a complie error with the code below but it didn't auto generate my code for me. The varible backcolor that is returned was just an internal varible in my usercontrol of the type color.

public override Color BackColor
            {
                  get
                  {
                        return backcolor;
                  }
                  set
                  {
                        backcolor = value;
                        this.textBox1.BackColor = backcolor;
                  }
            }

I will paste in work helped me work it out below. I figured out that from the help below that it wasn't returning the right type even though I was returning a color I thought that maybe the base returned something that I didn't know about. I have noticed that if you have a compile error in your code that the designer won't fully auto generate. When the error is fixed the auto generated code comes back. Interesting hey. I hope this help you.


When an instance method declaration includes an override modifier, the method is said to be an override method. An override method overrides an inherited virtual method with the same signature. Whereas a virtual method declaration introduces a new method, an override method declaration specializes an existing inherited virtual method by providing a new implementation of that method.

The method overridden by an override declaration is known as the overridden base method. For an override method M declared in a class C, the overridden base method is determined by examining each base class of C, starting with the direct base class of C and continuing with each successive direct base class, until an accessible method with the same signature as M is located. For the purposes of locating the overridden base method, a method is considered accessible if it is public, if it is protected, if it is protected internal, or if it is internal and declared in the same program as C.

A compile-time error occurs unless all of the following are true for an override declaration:

An overridden base method can be located as described above.
The overridden base method is a virtual, abstract, or override method. In other words, the overridden base method cannot be static or non-virtual.
The overridden base method is not a sealed method.
The override declaration and the overridden base method have the same return type.
The override declaration and the overridden base method have the same declared accessibility. In other words, an override declaration cannot change the accessibility of the virtual method.

Regards

Simion
0
 
LVL 4

Expert Comment

by:caner_elci
ID: 10837920
Nice work Simion, but what's backcolor in the second sample? You base doesn't have a variable called backcolor, does it?
0
 
LVL 1

Expert Comment

by:simion_tishler
ID: 10839097
Well the second one was the one that didn't work. But when you declare a property called RowNumber just say, you need something to store it in and because variables are case senitive I call the internal one the same name but lower case like rownumber. That way I can see which internal varibles are linked to the properties.

So the varible backcolor that is returned was just an internal varible in my usercontrol of the type color.

0
 
LVL 4

Expert Comment

by:caner_elci
ID: 10840106
I see.. By the way, in your second property definition, new operator should work.. instead of override I mean.. Because, as far as I know, base.BackColor is not virtual, override or abstract... So it's not a good way to try to override it..
0
 
LVL 1

Expert Comment

by:simion_tishler
ID: 10855363
hmmm well thats something to think about. It's been nice solving this problem with you.

Regards

Simion
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Extention Methods in C# 3.0 by Ivo Stoykov C# 3.0 offers extension methods. They allow extending existing classes without changing the class's source code or relying on inheritance. These are static methods invoked as instance method. This…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

708 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now