views:

1062

answers:

5

I have a gridview and usercontrol on the page, I want to alter gridview from usercontrol. how can i do that?

And also how can I call functions in usercontrol's "host" page from the usercontrol?

UPDATE:

I have a dropdownlist inside this usercontrol, when the it's SelectedIndexChanged event is triggered i want the gridview on the host page to DataBind().

(Then, gridview using objectdatasource will read this dropdownlist selected item and use it as select parameter)

Also if it possible to make it as general as it possible, because the altered control is not always a gridview...

Thanks

+1  A: 

Use

GridView grid = Page.FindControl("GridViewID") as GridView;
if (grid != null) {
      // ... grid.Method()...
}

It's a good approach to let the host page pass the grid view ID as a property to the user control, rather than hardcoding it.

Mehrdad Afshari
A: 

EDIT: In your user control, simply create a public property to hold the grid. That property will then hold a reference to grid in the host page. For example, you could add the following to your UserControl's code behind.

public string CurrentGridID
{
  get;
  set;
}

public void ModifyGrid()
{
  //make changes to the grid properties
  GridView grid = Page.FindControl(CurrentGridID);
  grid.AutoGenerateColumns = false;
}

From your the page hosting the control, you could do something like this.

protected void Page_Load(object source, EventArgs e)
{
   this.myUserControl1.CurrentGridID = this.gridView1.ID;
}
ichiban
This has the disadvantage of not being able to declaratively mapping the grid view to the user control. The usual pattern used in ASP.NET (in things like validation controls and data sources) is to pass the ID as a string and let the child control look the thing up.
Mehrdad Afshari
That's a good point.
ichiban
+3  A: 

First of all, you would not want to do neither. That's against the concept of user control.

If you want to modify a gridview using the user control's state, you can expose the control's state and make the gridview to behave according to this state.

// This handles rowdatabound of gridview
OnRowDataBound(object sender, RowDataBoundEventArgs e)
{
    var control = e.Row.Find("UserControlId");
    if (control.SomeProperty == SomeValue)
        someTextBox.Value = "something";
}

If you really need to pass a handle of gridview to a user control, define a property on the user control of grid view type:

// This is a property of user control
public GridView Container { get; set; }

and set the control's container to the gridview, before accessing it.

userControl.Container = gridView;

If the user control is a part of the itemtemplate on the grid, since your user control is created while rows of the gridview are created, you can only this after you bind your gridview.

Finally, for calling a function on the container page, you can expose an event inside of your user control and bind to that event.

public delegate void SomethingHappenedEventHandler(object sender, EventArgs e);

// In user control:
public event SomethingHappenedEventHandler SomethingHappened;

// Trigger inside a method in user control:
SomethingHappenedEventHandler eh = SomethingHappened;
if (eh != null) eh(this, EventArgs.Empty);

// In page:
userControl.SomethingHappened = new SomethingHappendEventHandler(OnSomething);

private void OnSomething(object sender, EventArgs e)
{
    // When something happens on user control, this will be called.
}
Serhat Özgel
I have a dropdownlist inside this usercontrol, when the it's SelectedIndexChanged event is triggered i want the gridview on the host page to DataBind().
markiz
Last part of the answer still applies. Expose the event inside your user control (fire somethingHappened on SelectedIndexChanged) and catch it in the page and rebind the grid.
Serhat Özgel
Will I still need the first part?
markiz
No, you just need to expose the event and handle it in your page.
Serhat Özgel
Is there something missing in event declaration?How do I trigger this event?No delegate needed?
markiz
I just assumed the usage of built - in EventHandler. Now it should be more clear.
Serhat Özgel
A: 

Simply add a public method to your usercontrol's code-behind, then you can call this from the page and pass the gridview as a parameter:

public class MyUserControl : UserControl
{
  public void MyMethod(GridView gridview)
  {
    // do stuff with the gridview
  }
  ...
}

The second question is a bit more complicated. Because if you make your usercontrol depend on a specific page, it will no longer be reusable on other pages, e.g:

public class MyUserControl : UserControl
{
  public void AnotherMethod()
  {
     //get the current page and cast it to its type
     MyPage page = this.Page as MyPage;
     // now I can call the public methods of MyPage
     page.SomeMethod();
  }
  ...
}

A better solution would be to define an interface, which is implemented by the page. Then you can methods of that interface by casting the current page to the interface (and the controls can still be reused on other pages implementing the same interface):

public interface IMyInterface
{
  void SomeMethod();
}
public class MyPage : IMyInterface
{
  public void SomeMethod() { ... }
}
public class MyUserControl : UserControl
{
      public void AnotherMethod()
      {
         //get the current page and cast it to the interface
         IMyInterface page = this.Page as IMyInterface;
         // now I can call the methods of the interface
         if (page != null) page.SomeMethod();
      }
}
M4N
A: 

You should expose a public property that accepts the id of the server control you want to reference. You could then grab that control by querying Control.NamingContainer. You should not query Page, since you want to grab the control in your current context (you could be in a usercontrol with controls named the same as the page).

Dont forget the often overlooked IDReferencePropertyAttribute. It tells your designhost (usually Visual Studio) to provide autocompletion for the value using all controls in the current context.

To call stuff on your containing Page, just use the Page property. You need to cast this to your specific page class if you need to access your own methods.

Simon Svensson