Click here to Skip to main content
15,887,988 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi,

I got a Custom Control that is making the control flashing between two colors.
My problem is that I dont know how to do a Refresh() command from a static method.
I need to update all the custom controls from that static method.

I have tried to override Refresh().
C#
public override void Refresh()
{
    base.Refresh();
}


But how do I call the Refresh() function from the static method?

Thanks.
Posted
Comments
BillWoodruff 2-Nov-11 6:37am    
Please tag this question to indicate if it's WinForms or whatever. I think it would also be helpful if you clarified whether you add your custom controls at run-time, or design-time, or both.

You would have to pass into that static method, or register statically in the class, the controls that you want to refresh or some way of getting to them. For example you could pass in a form and refresh all members of that type on the form:

public static RefreshAll<T>(Control cc){
 foreach(Control c in cc.Controls){
  if(c is T) c.Refresh();
  RefreshAll<T>(c);
 }
}


called like

void Timer_Tick(object sender, TimerEventArgs e){
 RefreshAll<MyFlashyControl>(this);
}


... in the form. You can put that static method anywhere that makes sense.
 
Share this answer
 
v2
Comments
BillWoodruff 2-Nov-11 7:59am    
+5 That's a fascinating use of recursion in a static method using Linq !
BobJanova 2-Nov-11 8:16am    
I see no LINQ? It's a fairly standard control-walking use of recursion, I think – just by being a static method it allows you to start from anywhere. (It could also be an extension method but I don't really like those and tend to write statics instead.)
BillWoodruff 2-Nov-11 8:31am    
Hi Bob, I think I "jumped the gun" there: subliminally (?) registering the absence of a return type in the recursive method declaration ... which is probably an accident of copy-paste, and will cause a compile error ... and the usual pre-recursion test for the presence of whether or not the current control contains any controls ... as Linq.

One further comment: if the OP's scenario is interpreted as meaning that he's using 'Refresh to make sure that his custom-controls are switching colors ... and if that refresh is frequent ... then I would question the 'economy' of using a full recursion where every Control is compared with "T" ... unless ... there is some under-the-hood compiler optimization in such cases I don't know about.

I gotta watch that subliminal tendency more carefully, or come up with a better excuse than that :)

thanks, Bill
BobJanova 2-Nov-11 9:45am    
Ah, yes, that is just a mistake, haha. No copy paste, I just type answers straight into CP, so sometimes that happens.

It depends how complex the form which he wants this magic to happen on is whether walking the control tree every timer tick is a problem. It might be better to cache results for a particular source control and provide a 'decache me' method to avoid the permanent reference problem. Personally I'm not sure a static RefreshAll is the right approach but that's what is asked for.
My "crystal ball" is cloudy, but ... I'm going to guess that the "static method" needs a reference to the instances of the custom controls (going to assume they are User Controls) which it doesn't have now ... since a Control, by definition, cannot be 'static.'

Another guess might be the static method is in a static class that, perhaps, is a 'factory' that returns instances of your custom control on-demand that are then "sited" in some run-time container.

If you are speaking about adding instances of your custom control at run-time:

1. define a static collection of type 'YourCustomControl,' and then, at the place in the code where your custom control is created, add it to that collection. Then, of course, you make that collection accessible to the static method that can enumerate it, and invoke the Refresh() method on each custom control.

Something to think about: if the static method is not "defined in" the object where the custom controls are created: how do you make it accessible to the instance ... for example, a Form ... where the new custom controls are created ?

If you are speaking about adding instances of your custom control at design-time:

Assuming you are drag-dropping your custom control into some container object (Form, Panel, etc.), then you are going to need to do something in the custom control code that does the right thing to add the new instance to the static list of instances.

Is there a 'happy solution' which will work for both design-time and run-time ? Well, I think so :)

1. Because you may have instances of your custom controls on more than one Form, or, in one Form or other container inside another (nested), my choice would be to make a static class that encapsulates what you need to do to all instances of the custom controls everywhere.
C#
public static class TheStaticClass
{
    public static List<YourCustomControl> YCCList = new List<YourCustomControl>();

    public static void RefreshYCCs()
    {
        foreach (YourCustomControl ycc in YCCList)
        {
            ycc.Refresh();
        }
    }
}
2. Now you can take advantage of the Load event of your custom control to update the List which will work at design-time, or when you create instances at run-time:
C#
private void YourCustomControl_Load(object sender, EventArgs e)
{
    // seeing is believing ... ?
    //Console.WriteLine("custom control added");
    //
    TheStaticClass.YCCList.Add(this);
    //
    // suggest you set a break-point here and examine the 'Count of the YCCList
    // both initially, and as you may add instances of your custom control at run-time
    //
}
3. And now from somewhere else (inside some other Form, or whatever) in your code you can invoke the refresh of all instances of your custom control:
C#
private void button1_Click(object sender, EventArgs e)
{
    TheStaticClass.RefreshYCCs();
}
4. In this scenario my personal preference would be to move the code (if any) that creates a new instance of the custom control at run-time into the static class (i.e., make it a 'factory' class), and when I called the method in the static class, I'd pass it the container the new instance is to be inserted into ... but that's a matter of taste, or style.
C#
public static void AddNewCustomControl(Control targetControl)
{
    targetControl.Controls.Add(new YourCustomControl ());
}
Note that in outlining this little snippet I did not consider the possibility there might be some type of container object into which you might wish to insert an instance of your custom control that just might not have its internal ControlsCollection accessible in the 'usual' way. Paranoia is the friend of pest-control ?

~

There are other strategies implied here, and I'm sure you'll hear some 'other visions' of those strategies, and others that I never dreamed of, on this thread :)

 
Share this answer
 
v3
Comments
BobJanova 2-Nov-11 7:38am    
This is a good answer. The only comment I would make is that if you register instances in a static registry like that, they are never garbage collected, so if you add and remove controls, you will have a resource leak. This is one reason I went with the call-time enumeration in my answer.
BillWoodruff 2-Nov-11 8:04am    
Thanks, Bob, I'm curious: if I put a specific static method in that static class that maintains the collection of custom-controls ... that took as a parameter a reference to one of the instances of the custom-control, and then removed it from the collection: would that effectively prevent a memory leak ?
BobJanova 2-Nov-11 8:14am    
As long as there is no permanent reference to instances stored in a static state variable, then the instance can be disposed. For example, if the control itself reacted to being removed from the UI by removing itself from this collection, you would be ok.

The usual mistake is to forget about event handlers – hooking to a static event creates a permanent reference to you, until you unregister it. But registering yourself directly in a collection like in your example is a more obvious permanent reference.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900