views:

765

answers:

6

I'm new to usercontrols, having only created one so far, so bear with me. I've been reading today that usercontrols are supposed to be self-contained and not rely on any information from the parent container. I get that part, but what I'm having trouble understanding is the "right" way to design my program around that principle.

I'm making a web form in C# in which there's a page with a usercontrol in that page. I've made the usercontrol in its ascx file and dragged it into my aspx page. The usercontrol is a couple date boxes and a gridview to show the results of an SQL stored procedure.

I'd really like to reuse this control, but I can't figure out how to "tell" the usercontrol what stored procedure I'd like to run for the specific page I'm on without violating the "don't rely on the parent container" rule.

Thanks

A: 

So you have some things inside of this user control that will databind to a dataset that is returned by the stored procedure?

Here's one way to handle it: Instead of trying to communicate the stored procedure to the user control, make the dataset that the user control will rely upon a public property of the user control.

At runtime, your code that is outside of the user control will run the appropriate stored procecure, and set the dataset property on your user control to the result returned by the stored proc.

JMarsch
+6  A: 

Don't rely on the parent container doesn't mean you can't communicate. Expose a property in the user control which the parent will set. But have a default value so it doesn't crash.

Also, if this is a very specific control, there's no reason it would be bad to rely on the parent. It might not be ideal, but you would be using the user control to provide a separation of code.

marcc
+2  A: 

Your control does not need to know where it's data came from. It does not need to know about the stored procedure or anything else. All it needs to know is the data that it needs to show. If I understand your control right, it's a grid with some date filters. It will receive data, show that data and filter it by date. That's fine, all it needs to know is the data it needs to show and and maybe a default start and end date from the parent.

JP Alioto
+2  A: 

You're missing out on the true power of user controls if you don't allow it to communicate with it's parent. I think you may be taking encapsulation a little too far in this case.

Assume you have a user control that is just a table or a gridview of various user data. Inevitably that user control is going to need to know about the unique identifier of the user in order to pull it's data from wherever it is, which of course forces you to make a public property that the parent page can set.

Also, keep in mind that there will be times when an action within a user control needs to trigger an action on the parent. Event delegates come into play here, and they're extremely useful and, in my opinion, make user controls even more useful.

Just drop the whole idea about user controls and parents not talking back and forth, and you'll find things much easier.

Jagd
A: 

As everyone else has pointed out, your user control needs to have a standard way of communicating its intentions and behaviors. This doesn't mean that you have to have a reference to the container, and therefore know what (MyPage.aspx) actually contains it.

The thing that I've found indispensable while working with user controls is events. Learn events and how to use them. Events are a great way of communicating behavior.

In your example, I may split out your criteria (date textboxes) into its own user control. Create a new class that inherits from EventArgs, that contains your criteria (DateTime fields). When the user clicks search, fire an event (of type EventHandler<YourEventArgs>) with your custom EventArgs. The page will handle the event, query the database, and then pass the results into a public or internal method on your second user control, which displays the records.

The key here, your criteria control can be reused on different pages if you have the need of calling different stored procedures. Think of insert vs update scenarios. Often times, the UI elements are the same. You can create one control and use it on two different pages with two different behaviors (AddRecord.aspx and UpdateRecord.aspx). Also, your control that displays records is very easily reused.

One huge benefit is that your pages and controls become rather small. Each control/page is really only concerned with its small subset of functionality. Your code will become less daunting and easier to maintain.

Aaron Daniels
A: 

"tell" the usercontrol what stored procedure I'd like to run

Sounds like you're looking for events/delegates
Have the control expose an event, and let the parent add a handler (perhaps in the constructor, if you want to force it to add one and only one event)
Alternatively, you could use Command/Strategy pattern - have the parent encapsulate the method, and send the encapsulating object to the control in its constructor.

T.R.