Problem with WebPart postback...? (Clickevent not executed)


Joined
Mar 17, 2008
Messages
2
Reaction score
0
Hey there,



Recently I've started developing webparts (for SharePoint). Since I have not much experience with ASP, .NET and developing web-applications, please be very explicit if you know a solution to my problem :)



The problem is that when I started making the webpart, I had no idea of the influence of the postback on the behavior of my webpart. So, my webpart might be developed in a bit of an awkward manner, because I was so ignorant to think that the webpart would maintain it's state in some way, like a desktop application would do. Anyhow, let me first explain the basics of the webpart.



The application reads an XML file which contains a certain folder and file structure. This folder/file structure has to be rendered in the webpart in a windows explorer-like way. So, all folders should be visible on the left side in a tree structure (so I used a TreeView), and on the right side of the webpart, the contents of the selected folder should be displayed with thumbnails and all (so I used a Table). Because I thought the webpart would remember some things, I figured it would be smart to 'prerender' all tables instead of creating them dynamically when a folder is clicked (this seems to be worse however with the postback stuff happening... It would still be better if there is some way to prevent the webpart from loading all over again after a clickevent...).



Then my idea was to just simply implement the clickevent of the TreeView (SelectedNodeChanged) so that the folder's (premade) table is loaded in the right side of the screen when you click on a node in the treeview (which works just fine). Then I implemented the clickevent of the thumbnails in the table (which are ImageButtons) in the following way: the clickevent will say "which ImageButton fired the event, what's his ID and do I have a treenode with the same ID? Yes? Alrighty then, then I will select that TreeNode and raise a clickevent on the TreeView", which will cause the table of the selected folder in the treeview to be loaded (so the clickevent of the ImageButton is actually kind of rerouted). The folders also contain files, these have a javascript attached to them which works fine.



Maybe you can guess what goes wrong now. When you use the treeview to navigate, everything works just fine. But when you click on an ImageButton in the table, it should go and execute the method for the clickevent for that ImageButton. But it never does that. Because first the postback happens. All controls are created and rendered again and the webpart is back to it's original state, meaning that there is no ImageButton in a table on the right side to execute the click event. So it just does nothing instead (At least I THINK that that is the problem..). Funny thing is, if I load a table on the right side in the original state, and let's say there's an ImageButton with a certain ID, then it WILL execute a clickevent if I have clicked on another ImageButton in another table, but with the same ID...




Here's some (I think relevant) which could help you understand more of what I'm doing:



protected override void CreateChildControls()

{

root = Environment.GetEnvironmentVariable("Svrt");
treeNodes = new List<BTreeNode>();

table = new Table(); //The table for the right side
table.Width = 500;
TableRow contentRow = new TableRow();
contentCell = new TableCell();
contentRow.Cells.Add(contentCell);
table.Rows.Add(contentRow);
Controls.Add(table);

folderTV = new TreeView(); //The treeview for the left side...
folderTV.SelectedNodeChanged += new EventHandler(node_Click);
folderTV.ImageSet = TreeViewImageSet.BulletedList;

//Load the XmlDocument containing all folders and files as nodes
XmlDocument doc = new XmlDocument();
doc.Load(root + "/wpresources/XML/folders.xml");
//Select all headnodes
XmlNodeList heads = doc.SelectNodes("folder");
//Parse through all headnodes

for (int i = 0; i < heads.Count; i++)
{
XmlElement parentElem = (XmlElement)heads;

BTreeNode* parentFolder = new BTreeNode(getCaption(parentElem)); //make a treenode for this element
treeNodes.Add(parentFolder); //Add the treenode to the treenodes list
appendChildren(parentElem, parentFolder)**; //Add children to the treenodes (recursive method)
folderTV.Nodes.Add(parentFolder); //Add this 'head'node to the treeview
}

createTables(); //Method to set table content for all treenodes
Controls.Add(folderTV);
}


* The BTreeNode is an extension of the TreeNode. This BTreeNode has lists of the Xml Elements representing it's subfolders and subfiles, in order to be able to quickly create the tables and access the properties of the folder/file. The BTreeNode also 'gets' it's table, once it's created in the createTables method.

** The appendChildren method checks the XML element if there are subfolder elements, if so it adds them as a treenode child and it gives the subfolder XML element to the appendChildren method, causing the method to add subfolders recursively. Each XmlElement representing a subfolder or file is also added to lists of the BTreeNode (see BTreeNode explanation above).



private void createTables()
{
for (int h = 0; h < treeNodes.Count; h++) //parse through all the treenodes
{
BTreeNode node = treeNodes[h]; //get a treenode
int x = 0;
int foldersamount = node.Folders.Count; //see how much folders this node has
int filesamount = node.Files.Count; //see how much files this node has
decimal cols = 4; //we will make four colums
decimal rowsdec = ((decimal)foldersamount + (decimal)filesamount) / cols;
int rows = Convert.ToInt32(System.Math.Ceiling(rowsdec)); //and as much rows as needed

for (int i = 0; i < rows; i++) //for each row to be made
{
TableRow row = new TableRow(); //make a row
for (int j = 0; j < cols; j++) //and in this row, make columns :)
{
//Creating minitable with two cells called c1 and c2
(code not shown because not interesting)

if (x < foldersamount) //if there are still folders to be added
{
XmlElement folderElem = (XmlElement)(node.Folders[x]); //get a folder

String caption = getCaption(folderElem); //get the caption for this folder (for the label)
ImageButton folder = new ImageButton(); //create an imagebutton for the folder
folder.Click += new ImageClickEventHandler(folder_Click); //and give it a clickevent
folder.ImageUrl = getImageType(folderElem); //set the correct image by this file
folder.ID = caption;
c1.Controls.Add(folder); //add this to the cell in the table
Label label = new Label(); //make a label to go under the folder
label.Text = caption; //set the correct caption
c2.Controls.Add(label); //and add the label
x++;
}

else if ((x - foldersamount) < filesamount) //if there are files to be added
{
XmlElement fileElem = (XmlElement)(node.Files[x - foldersamount]);
String filepath = getFilePath(fileElem, ""); //get the filepath of this file
String caption = getCaption(fileElem); //and get the caption (for the label)
ImageButton file = new ImageButton();
file.Attributes.Add("onClick", "_openmodel('" + filepath + "')"); //add a clickevent to the file which will execute javascript which will open a model
file.ImageUrl = getImageType(fileElem); //set the correct image for this file
file.ToolTip = caption.ToLower() + " maken";
c1.Controls.Add(file);
Label label = new Label();
label.Text = caption;
c2.Controls.Add(label); //and add the label with the caption under the image
x++;
}

cell.Controls.Add(ta); //add the minitable to the cell
row.Cells.Add(cell); //add the cell to a row
}

node.Content.Rows.Add(row); //when a row is done
}
}
}

protected override void RenderWebPart(HtmlTextWriter output) {
//renders the treeview and the table with the one cell in which the prerendered tables can be put.
}


So this is basically everything that happens on rendering. Now, the clickevents look like this:

protected void node_Click(Object sender, EventArgs e)
{
if (contentCell.Controls.Count != 0) //if there already is content \
{
Table curTable = (Table)contentCell.Controls[0]; //select the content...
contentCell.Controls.Remove(curTable); //and remove iT
}

BTreeNode selNode = (BTreeNode)(((TreeView)sender).SelectedNode); //get the selected node
contentCell.Controls.Add(selNode.Content); //and add it's content (table) to the table
}


private void folder_Click(Object sender, EventArgs e)
{
String foldername = ((ImageButton)sender).ID; //get the name of the folder that's been clicked on

int i = 0;
bool found = false;
while (i < treeNodes.Count && found == false) //search the treenodes list
{
BTreeNode node = treeNodes;
if (node.Text == foldername) //...until you find a node which corresponds with the folder clicked on
{
found = true;
node.Select(); //and then select this node..
node_Click(folderTV, null); //and trigger the clickevent of the treeview
}
i++;
}
}


Any help is much appreciated! I just need the application to work so that when I click on an ImageButton, the event can always be executed! I read some things about Page_Load, IsPostBack, AutoPostBack, ViewState etc but I feel like searching for a needle in a haystack when it comes to that (because of my limited experience with this stuff). And maybe you know an entire different way to make this application work; anything is much appreciated!



Hope you can find the time to help me out,



Greetings,

Jip
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top