I am trying to build a website that has a custom File Explorer. Eventually I hope to build it out further and allow uploads, but I'm facing an issue calling it from the code behind.
My user control contains a Treeview, and if call it like this:
<fe:FileExplorer filePath="/Resources/" runat="server"></fe:FileExplorer>
everything works fine, but when I call it from the code behind like this:
FileExplorer uc = (FileExplorer)LoadControl("~/Controls/FileExplorer.ascx");
uc.filePath = "/Uploads/Newsletter/";
PAGECONTROLS.Controls.Add(uc);
I have an issue with the Post back.
The issue appears to be when I'm getting the selected node. It grabs the selected node when I use the .Net inline, but when I use the code behind it seems to loose the post back:
TreeNode nd = FolderTree.SelectedNode; <-- Always Null when called in code behind.
Below is the Code Behind:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Troop_101.Controls
{
public partial class FileExplorer : System.Web.UI.UserControl
{
public string FilePath;
public string filePath{
set { FilePath = value; }
get { return FilePath; }
}
protected void Page_Load(object sender, EventArgs e)
{
string RootFilePath = Server.MapPath(FilePath);
if (!IsPostBack)
{
DirectoryInfo rootDir = new DirectoryInfo(RootFilePath);
TreeNode rootNode = new TreeNode(rootDir.Name, rootDir.FullName);
FolderTree.Nodes.Add(rootNode);
TraverseTree(rootDir, rootNode);
FolderTree.CollapseAll();
}
string ReturnStr = "";
TreeNode nd = FolderTree.SelectedNode;
if (nd != null)
{
ReturnStr = getFolderContent(nd.Value);
}
else
{
ReturnStr = getFolderContent(RootFilePath);
}
RESOURCE_FolderContent.InnerHtml = ReturnStr;
foreach (TreeNode tn in FolderTree.Nodes)
{
tn.Expand();
}
}
private void TraverseTree(DirectoryInfo currentDir, TreeNode currentNode)
{
foreach (DirectoryInfo dir in currentDir.GetDirectories())
{
TreeNode node = new TreeNode(dir.Name, dir.FullName);
currentNode.ChildNodes.Add(node);
TraverseTree(dir, node);
}
}
private string getFolderContent(string filePath)
{
string ReplacePath = Server.MapPath(FilePath);
var info = new DirectoryInfo(filePath);
var fileInfo = info.GetFiles();
string LinkTemplate = "<table><tr><td><img src=\"{1}\" height=\"25px\"></td><td style=\"vertical-align:center;\">{2}</td></tr></table>";
string ReturnFiles = "";
if (fileInfo.Length <= 0)
{
ReturnFiles = "No Files In Folder<br />";
}
foreach (FileInfo file in fileInfo)
{
string FileExt = file.Extension.ToLower().Replace(".", "");
if (!File.Exists(HttpContext.Current.Server.MapPath("/images/ExtensionIcons/" + FileExt + ".png")))
FileExt = "_blank";
string fir = filePath.Replace(ReplacePath, "");
ReturnFiles += String.Format(LinkTemplate, FilePath + fir + "/" + file.Name, "/images/ExtensionIcons/" + FileExt + ".png", file.Name);
}
return ReturnFiles;
}
}
}
And here is the .NET
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="FileExplorer.ascx.cs" Inherits="Troop_101.Controls.FileExplorer" %>
<div style="width:90%; border:thick solid #656565;margin:0 auto; background-color:#ffffff; padding:5px;" class="tableroundcorners">
<style type="text/css">
.node_left {
padding:5px;
}
</style>
<table style="width:100%;height:350px;">
<tr>
<td id="RESOURCE_FileTree" runat="server" style="width:150px;border-right:solid #757575 thin;overflow:auto;">
<asp:TreeView ID="FolderTree" runat="server" NodeIndent="15" ShowLines="True" LineImagesFolder="~/Controls/FileExplorerTree">
<HoverNodeStyle Font-Underline="True" ForeColor="#6666AA" />
<NodeStyle Font-Names="Tahoma" Font-Size="8pt" Width="100%" CssClass="node_left" ForeColor="Black" HorizontalPadding="0px" NodeSpacing="0px" VerticalPadding="2px" />
<ParentNodeStyle Font-Bold="False" />
<SelectedNodeStyle Font-Underline="true" HorizontalPadding="0px" VerticalPadding="0px" BackColor="#cccccc" />
</asp:TreeView>
</td>
<td id="RESOURCE_FolderContent" runat="server" style="text-align:left;overflow:auto;">
</td>
</tr>
</table>
</div>
In the code behind make sure that your are adding the control in the OnInit method to ensure that the control exists prior to processing the post back data (before the page load event)
http://i.msdn.microsoft.com/dynimg/IC386473.png (ASP.NET LifeCycle)
Related
when i click on link button for adding more file upload then this add only 1 .. means 1 file upload which is already visible and 1 which is display on clicking on linkbutton ..
but when i click again on linkbutton for adding more then this not display ..
i try this
ok i do this
<form id="form1" runat="server">
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">upload</asp:LinkButton><br />
<asp:Panel ID="Panel1" runat="server"></asp:Panel>
<asp:Button ID="Button1" runat="server" Text="submit" OnClick="Button1_Click" />
</form>
suppose there is file upload control.. when we select file by clicking on browse and then click on upload then file name with extension i.e. abc.doc should be display ... then when we use again same file upload and click on browse and select another file then file will be display i.e. xyz.pdf.. so there is two files abc.doc and xyz.doc .. so this is want to do .. i want to upload files and display these uploaded files
UPDATE
for this i try this
protected void LinkButton1_Click(object sender, EventArgs e)
{
fileuploadd(FileUpload1.FileName);
}
public void fileuploadd(string filename)
{
try
{
HttpFileCollection hfc = Request.Files;
for (int i = 0; i < hfc.Count; i++)
{
HttpPostedFile hpf = hfc[i];
if (hpf.ContentLength > 0)
{
SMSEntities s = new SMSEntities();
uploaded_file u = new uploaded_file();
{
u.fileupload = filename;
}
s.uploaded_file.Add(u);
s.SaveChanges();
}
//hpf.SaveAs(Server.MapPath("upload") + "\\" + System.IO.Path.GetFileName(hpf.FileName));
Response.Write("<b>File: </b>" + hpf.FileName + " <b>Size:</b> " + hpf.ContentLength + " <b>Type:</b> " + hpf.ContentType + " Uploaded Successfully <br/>");
}
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
}
so when i select file and click on upload then file name is display .. but when i select again file and click on upload then 1st file name is disappear and 2nd file name is display where as i want both ..
so how i display both filenames ... and when click on submit then record files should be inserted in tables individually i am done with this but not with both filename display at a time ..
Create a FileUpload Control on your .aspx like:
<asp:FileUpload runat="server" ID="UploadImages" AllowMultiple="true" />
then in your code behind:
protected void uploadFile_Click(object sender, EventArgs e)
{
if (UploadImages.HasFiles)
{
foreach (HttpPostedFile uploadedFile in UploadImages.PostedFiles)
{
uploadedFile.SaveAs(System.IO.Path.Combine(Server.MapPath("~/Images/"),
uploadedFile.FileName)); listofuploadedfiles.Text += String.Format("{0}<br />", uploadedFile.FileName);
}
}
}
Multiple File Upload
HI Super User Previously I also had same Problem.
What i Actually did was I have Created 5 File Control's For Example
1) FileUpload1
2) FileUpload2
3) FileUpload3
4) FileUpload4
5) FileUpload5
And I have 4 of them as Hidden on load.
On click of 1 st I am showing 2nd One and on click of 2nd I am showing the 3rd one and So on...
In the Controller/Method I am checking if the File Control is not null then proceeding with the normal File Upload Process By taking Array of File Uploads.
<div id="flOther" runat="server">
<div id="fileOtherUploadarea">
<asp:FileUpload ID="flOtherUPL" runat="server" />
</div>
<input style="width: 20px; border: 0px none; background-color:transparent;" id="btnOtherAddMoreFiles" type="button" onclick="AddOtherMoreImages();" class="icon-plus-sign" />|
<asp:LinkButton ID="lnkOtherUpload" OnCommand="btnLnk_UploadOtherFiles" CommandArgument='<%# Eval("ID") %> 'runat="server">Upload Files</asp:LinkButton>
</div>
<script language="javascript" type="text/javascript">
function AddMoreImages() {
if (!document.getElementById && !document.createElement)
return false;
var fileUploadarea = document.getElementById("fileUploadarea");
if (!fileUploadarea)
return false;
var newLine = document.createElement("br");
fileUploadarea.appendChild(newLine);
var newFile = document.createElement("input");
newFile.type = "file";
newFile.setAttribute("class", "fileUpload");
if (!AddMoreImages.lastAssignedId)
AddMoreImages.lastAssignedId = 100;
newFile.setAttribute("id", "FileUpload" + AddMoreImages.lastAssignedId);
newFile.setAttribute("name", "FileUpload" + AddMoreImages.lastAssignedId);
var div = document.createElement("div");
div.appendChild(newFile);
div.setAttribute("id", "div" + AddMoreImages.lastAssignedId);
fileUploadarea.appendChild(div);
AddMoreImages.lastAssignedId++; }
</script>
protected void btnLnk_UploadOtherFiles(object sender, CommandEventArgs e)
{
int ID;
try
{
if (!String.IsNullOrEmpty(Convert.ToString(e.CommandArgument)))
{
ID = Convert.ToInt32(e.CommandArgument);
HttpFileCollection hfc = Request.Files;
for (int i = 0; i < hfc.Count; i++)
{
HttpPostedFile hpf = hfc[i];
if (hpf.ContentLength > 0)
{
string fileExtension = System.IO.Path.GetExtension(hpf.FileName);
if (ValidExtesion(fileExtension))
{
int MaxSizeAllowed = Convert.ToInt32(ConfigurationManager.AppSettings["MaxFileSize"]);
if (hpf.ContentLength < MaxSizeAllowed)
{
int lastIndex = Convert.ToInt32(hpf.FileName.LastIndexOf("\\"));
string FileName = DateTime.Now.Millisecond + hpf.FileName.Substring(lastIndex + 1);
string FileName1 = hpf.FileName.Substring(lastIndex + 1);
FileName = FileName.Replace(" ", "");
StringBuilder AncTag = new StringBuilder();
AncTag = AncTag.Append("<a href='Attachments/AMT/'" + FileName + "' target='_blank'>'" + FileName1 + "' </a>");
string strAncTag = AncTag.ToString();
strAncTag = strAncTag.Replace("'", "");
hpf.SaveAs(AppDomain.CurrentDomain.BaseDirectory + "Attachments/AMT/" + FileName);
obj.UploadOtherFiles_ProblemDescription(ID, strAncTag);
}
else
{
}
}
else
{
}
}
}
}
}
catch (Exception ex)
{
ErrorLog objER = new ErrorLog(ex);
}
finally
{
obj = null;
grdPDC.EditIndex = -1;
}
}
I have a FileUpload Control in my Asp.Net Webforms Project that doesn't wasn't to run the if(fuPostPhotoCreate.HasFile) { } block.
Here's the relevant aspx page code:
<asp:UpdatePanel ID="upMain" runat="server">
<ContentTemplate>
<div class="form-group">
<label for="txbPostPhotoCreate">Picture</label>
<asp:FileUpload ID="fuPostPhotoCreate" runat="server" ToolTip="Upload Picture" />
<asp:RegularExpressionValidator ID="revPostPhotoCreate" runat="server" ControlToValidate="fuPostPhotoCreate" ValidationExpression="([a-zA-Z0-9\s_\\.\-:])+(.png|.jpg|.jpeg|.gif)$" CssClass="text-danger" ErrorMessage='Please select a valid image format (".png", ".jpg", ".jpeg" or ".gif")' Display="Dynamic" />
</div>
<asp:LinkButton ID="btnCreatePost" runat="server" CssClass="btn btn-success" OnClick="btnCreatePost_Click" CausesValidation="true" ToolTip="Create Post" >
<span class="glyphicon glyphicon-plus"></span>
Create Post
</asp:LinkButton>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnCreatePost" />
</Triggers>
</asp:UpdatePanel>
Then I have the following in the aspx.cs page:
protected void btnCreatePost_Click(object sender, EventArgs e)
{
// (1) Some non relevant code
if (fuPostPhotoCreate.HasFile)
{
// (2) More non relevant code
}
// (3) Final non relevant code
}
My problem is that the fuPostPhotoCreate.HasFile always returns false even when I have uploaded a file and it's in the the fuPostPhotoCreate control. Therefor the non relevant code (2) never gets run (when it should get run when the fuPostPhotoCreate contains a file.
What could I be doing wrong? The non relevant code (1) and (3) does run successfully.
EDIT:
Here is the full code of that button click:
if (!Page.IsValid)
return;
try
{
var post = new Models.EF.Post();
post.DateCreated = DateTime.Now;
post.Title = txbPostTitleCreate.Text;
post.Body = txbPostBodyCreate.Text;
post.IsPublic = cbxPostPublicCreate.Checked;
int postId = efService.CreatePost(post);
gvDisplayPosts.DataBind();
if (fuPostPhotoCreate.HasFile)
{
//? Get filename extension
string fileName = Path.GetFileName(fuPostPhotoCreate.FileName);
string extension = fileName.Substring(fileName.LastIndexOf('.'));
//? Specify the path to save the uploaded file to.
string tempPath = Server.MapPath("~/Uploads/Temp") + "\\" + postId.ToString() + extension;
string savePath = Server.MapPath("~/Uploads/Posts") + "\\" + postId.ToString() + extension;
string saveThumbnailPath = Server.MapPath("~/Uploads/Posts/Thumbnails") + "\\" + postId.ToString() + extension;
#region Remove EXIF Data
var image = System.Drawing.Image.FromFile(tempPath);
if (Array.IndexOf(image.PropertyIdList, 274) > -1)
{
var orientation = (int)image.GetPropertyItem(274).Value[0];
switch (orientation)
{
case 1:
// No rotation required
break;
case 2:
image.RotateFlip(RotateFlipType.RotateNoneFlipX);
break;
case 3:
image.RotateFlip(RotateFlipType.Rotate180FlipNone);
break;
case 4:
image.RotateFlip(RotateFlipType.Rotate180FlipX);
break;
case 5:
image.RotateFlip(RotateFlipType.Rotate90FlipX);
break;
case 6:
image.RotateFlip(RotateFlipType.Rotate90FlipNone);
break;
case 7:
image.RotateFlip(RotateFlipType.Rotate270FlipX);
break;
case 8:
image.RotateFlip(RotateFlipType.Rotate270FlipNone);
break;
}
//This EXIF data is now invalid and should be removed.
image.RemovePropertyItem(274);
}
image.Save(savePath);
image.Dispose();
var tempDir = new DirectoryInfo(Server.MapPath("~/Uploads/Temp"));
foreach (FileInfo file in tempDir.GetFiles())
{
file.Delete();
}
#endregion
//? Convert savePath photo to thumnail and save to saveThumbnailPath
var fullImage = System.Drawing.Image.FromFile(savePath);
var thumbnailImage = new ImageResizer.ImageJob(fullImage, saveThumbnailPath, new ImageResizer.Instructions("width=150;mode=stretch;autorotate=false"));
thumbnailImage.Build();
string dbPathName = "~/Uploads/Posts/" + postId.ToString() + extension;
string dbThumbnailPath = "~/Uploads/Posts/Thumbnails/" + postId.ToString() + extension;
efService.SetPostPath(postId, dbPathName);
efService.SetPostThumbnailPath(postId, dbThumbnailPath);
}
//? Clear Fields
txbPostTitleCreate.Text = string.Empty;
txbPostBodyCreate.Text = string.Empty;
cbxPostPublicCreate.Checked = false;
//? Hide pnlAddPost
pnlAddPost.Visible = false;
}
catch (Exception ex)
{
string errorMessage = ex.Message.ToString();
lblExceptionMessage.Text = errorMessage;
lblExceptionMessage.Visible = true;
}
Note:
I have found that it seems to work if I change the file to be uploaded at least once before submitting.
I've just started playing with developing in SP2010, so I'm complete begginer .
I've created simple console application with code like this :
using (SPSite currentSite = new SPSite("http://win-e9840laitme"))
{
using (SPWeb currentWeb = currentSite.OpenWeb())
{
SPList myList = currentWeb.Lists["List1"];
string currentUserName = currentWeb.CurrentUser.Name;
SPQuery queryInformationAboutCurrentUser = new SPQuery();
queryInformationAboutCurrentUser.Query = "<Where>" +
"<Eq><FieldRef Name='EmployeeName'/><Value Type='Text'>" + currentUserName + "</Value></Eq>" +
"</Where>";
List<EmployeeInfo> listEmployeeInfo = new List<EmployeeInfo>();
SPListItemCollection collectionEmployee = myList.GetItems(queryInformationAboutCurrentUser);
foreach (SPListItem info in collectionEmployee)
{
EmployeeInfo eInfo = new EmployeeInfo();
eInfo.Deparment = info["Office"].ToString();
listEmployeeInfo.Add(eInfo);
}
foreach (EmployeeInfo eI in listEmployeeInfo)
{
SPQuery querySameOffice = new SPQuery();
querySameOffice.Query = "<Where>" +
"<Eq><FieldRef Name='Office'/><Value Type='Choice'>" + eI.Deparment + "</Value></Eq>" +
"</Where>";
SPListItemCollection collectionEmployeeDisplay = myList.GetItems(querySameOffice);
foreach (SPListItem item in collectionEmployeeDisplay)
{
Console.WriteLine(item["EmployeeName"].ToString() + " " + item["PhoneNumber"].ToString() + "\n");
}
}
}
}
Now I want to use that code inside sharepoint project , and instead of putting result of SPQuery on Console , I want to populate HTML table with the result staticly(without JS or Jquery , if it is possible).
I've created sp project and added ApplicationPage.
My idea was to use StringBuilder and something like this :
StringBuilder html = new StringBuilder();
html.Append("<table border = '1'>");
//Building the Header row.
html.Append("<tr>");
html.Append("<th>");
html.Append("EmployeeName");
html.Append("</th>");
html.Append("<th>");
html.Append("PhoneNumber");
html.Append("</th>");
html.Append("</tr>");
and in the last foreach loop this code :
foreach (SPListItem item in collectionEmployeeDisplay)
{
html.Append("<tr>");
html.Append("<td>");
html.Append(item["EmployeeName"].ToString());
html.Append("</td>");
html.Append("<td>");
html.Append(item["PhoneBook"].ToString());
html.Append("</td>");
html.Append("</tr>");
}
//Table end.
html.Append("</table>");
//Append the HTML string to Placeholder.
PlaceHolder1.Controls.Add(new Literal { Text = html.ToString() });
I beleive there are more elegant solutions to this problem, and if you now it please give me idea .Thank you.
I've found a solution.First we need to add Repeater into PlaceHolderMain :
<asp:Repeater ID="rptEmployees" runat="server">
<HeaderTemplate>
<table border="1" style="width:70%">
<tr>
<td>Employee Name</td>
<td>Phone Number</td>
<td>Position</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("EmployeeName") %></td>
<td><%# Eval("PhoneNumber") %></td>
<td><%# Eval("Position") %></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
than create another class and add this code into final loop:
foreach (SPListItem item in collectionEmployeeDisplay)
{
DisplayEmployee dE = new DisplayEmployee();
dE.EmployeeName = item[Sol.PB1.Fields.EmployeeName].ToString();
dE.PhoneNumber = item[Sol.PB1.Fields.PhoneNumber].ToString();
dE.Position = item[Sol.PB1.Fields.Position].ToString();
display.Add(dE);
}
rptEmployees.DataSource = display;
rptEmployees.DataBind();
}
You cant use XSLT transformation to convert your SPQuery results to an HTML table. see example of Applying an XSLT Transform to a DataSet
I have ListView that display info from XML and to save to server from FileUpload that are on this ListView. I dont have problem to write to the XML, the problem is on save the FileUpload to folder.
I belive that i have mistake that i not seperate the listview to itemtemplate and insertemplate and edit...It must to? because the title going to correct place on XML, and even file name. but the file not saved to the folder.
For most tests i did - nothing happent after click on "update" BTN. when i add the int "i" to the items[i] somtimes it just update the xml without saving the file, and sometimes i get error of "out of index".
What is wrong?
ASPX code
<h2><asp:Label ID="LBL_number" runat="server" Text='<%#XPath("id") %>'></asp:Label></h2>
<h2>Small Image</h2> <asp:Image Width="100" CssClass="ltr" runat="server" ID="TB_small" ImageUrl='<%# XPath("small_image_url") %>'></asp:Image><asp:FileUpload ID="FU_small" runat="server" />
<br /><br /><br />
<h2>Big Image</h2> <asp:Image Width="300" CssClass="ltr" runat="server" ID="TB_big" ImageUrl='<%#XPath("big_image_url") %>'></asp:Image><asp:FileUpload ID="FU_big" runat="server" />
<br /><br />
<h2>Title</h2> <asp:TextBox runat="server" ID="TB_title" Text='<%#XPath("title") %>'></asp:TextBox>
<br /><br /><br />
<asp:Button CssClass="btn" ID="Button1" CommandArgument='<%#XPath("id") %>' runat="server" OnClick="update" Text="Update" />
<br />
<asp:Button ID="Button3" CssClass="btn" CommandArgument='<%#XPath("id") %>' runat="server" CommandName="del" OnClick="del" Text="מחק" />
<br /><br />
<br /><br />
</ItemTemplate>
</asp:ListView>
<asp:XmlDataSource ID="XDS_data" runat="server"
DataFile="~/App_Data/AM_data.xml" XPath="/Data/datas/data">
</asp:XmlDataSource>
C# Example only with the small file upload.
protected void update(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load(Path.Combine(Request.PhysicalApplicationPath, "App_Data/AM_data.xml"));
Button myButton = (Button)sender;
int i = Convert.ToInt32(myButton.CommandArgument.ToString());
var FU_small1 = (FileUpload)myButton.FindControl("FU_small");
string extenstion_small = System.IO.Path.GetExtension(FU_small1.FileName);
filename_small = Guid.NewGuid().ToString();
FileUpload fu2 = LV_data.Items[i].FindControl("FU_small") as FileUpload;
if (fu2.HasFile == true)
{
fu2.SaveAs(Server.MapPath("~/imgs/data/big" + filename_small.ToString() + extenstion_small.ToString()));
}
var TB_title = (TextBox)myButton.FindControl("TB_title");
string myString3 = TB_title.Text;
XmlElement el = (XmlElement)doc.SelectSingleNode("Data/datas/data[id='" + i + "']");
el.SelectSingleNode("small_image_url").InnerText = "~/imgs/data" + filename_small + extenstion_small;
el.SelectSingleNode("title").InnerText = myString3;
el.SelectSingleNode("big_image_url").InnerText = "~/imgs/data" + filename_big + extenstion_big;
doc.Save(Path.Combine(Request.PhysicalApplicationPath, "App_Data/AM_data.xml"));
Response.Redirect(Request.RawUrl);
}
There are several problems with your update method:
You need to find control inside container, not inside button. *Wrong approach : * var TB_title = (TextBox)myButton.FindControl("TB_title");
There's no guarantee that id will match ListView's item index. *Wrong approach : * FileUpload fu2 = LV_data.Items[i].FindControl("FU_small") as FileUpload;
etc.
I would suggest to change the method to this:
protected void update(object sender, EventArgs e)
{
int index = 0;
XmlDocument doc = new XmlDocument();
doc.Load(Path.Combine(Request.PhysicalApplicationPath, "App_Data/AM_data.xml"));
Button myButton = (Button)sender;
ListViewItem lvwItem = (ListViewItem)myButton.NamingContainer;
FileUpload FU_small1 = myButton.FindControl("FU_small") as FileUpload;
if (FU_small1 != null && int.TryParse(myButton.CommandArgument, out index))
{
string extenstion_small = System.IO.Path.GetExtension(FU_small1.FileName);
filename_small = Guid.NewGuid().ToString();
TextBox TB_title = myButton.FindControl("TB_title") as TextBox;
string myString3 = TB_title!= null ? TB_title.Text : string.Empty;
if (FU_small1.HasFile == true)
{
FU_small1.SaveAs(Server.MapPath("~/imgs/data/small/" + filename_small + extenstion_small));
}
XmlElement el = (XmlElement)doc.SelectSingleNode("Data/datas/data[id='" + index + "']");
el.SelectSingleNode("small_image_url").InnerText = "~/imgs/data/small/" + filename_small + extenstion_small;
el.SelectSingleNode("title").InnerText = myString3;
el.SelectSingleNode("big_image_url").InnerText = "~/imgs/data/big/" + filename_big + extenstion_big;
doc.Save(Path.Combine(Request.PhysicalApplicationPath, "App_Data/AM_data.xml"));
}
Response.Redirect(Request.RawUrl);
}
And here's a test project I have used to test this.
Finnaly, "foreach" solved it
protected void update(object sender, EventArgs e)
{
//Get xml file
XmlDocument doc = new XmlDocument();
doc.Load(Path.Combine(Request.PhysicalApplicationPath, "App_Data/AM_data.xml"));
//Set button for index it later by CommandArgument
Button myButton = (Button)sender;
foreach (ListViewItem item in LV_data.Items)
{
//Findcontrol of 2 fileupload on listview
FileUpload FU_small1 = (FileUpload)item.FindControl("FU_small1");
FileUpload FU_big1 = (FileUpload)item.FindControl("FU_big1");
//Check if are has file.
if (FU_small1.HasFile && FU_big1.HasFile)
{
//Get extension and genereate random filenames (for avoid ovveride)
FileInfo small_info = new FileInfo(FU_small1.FileName);
FileInfo big_info = new FileInfo(FU_big1.FileName);
string ext_small = small_info.Extension;
string ext_big = big_info.Extension;
string filename_small = Guid.NewGuid().ToString();
string filename_big = Guid.NewGuid().ToString();
//Set i value by button CommandArgument (look on aspx on question)
int i = Convert.ToInt32(myButton.CommandArgument.ToString());
//Get title from TextBox and set string from it
TextBox TB_title = myButton.FindControl("TB_title") as TextBox;
string myString3 = TB_title != null ? TB_title.Text : string.Empty;
//Save the files from the fileuploads we found, and write it on xml
FU_small1.SaveAs(Path.Combine(Request.PhysicalApplicationPath, "imgs/data/thumbs/" + filename_small + ext_small));
FU_big1.SaveAs(Path.Combine(Request.PhysicalApplicationPath, "imgs/data/big/" + filename_big + ext_big));
XmlElement el = (XmlElement)doc.SelectSingleNode("Data/datas/data[id='" + i + "']");
el.SelectSingleNode("small_image_url").InnerText = "~/imgs/data/thumbs/" + filename_small + ext_small;
el.SelectSingleNode("title").InnerText = myString3;
el.SelectSingleNode("big_image_url").InnerText = "~/imgs/data/big/" + filename_big + ext_big;
doc.Save(Path.Combine(Request.PhysicalApplicationPath, "App_Data/AM_data.xml"));
}
}
// Refresh the page
Response.Redirect(Request.RawUrl);
}
I am trying to get some values from a List and then create a html table with this data but I can't get it to work properly.
I have:
HtmlTable table = new HtmlTable();
HtmlTableRow row;
HtmlTableCell cell;
foreach(var item in Name)
{
row = new HtmlTableRow();
foreach(var familyName in item.familyName)
{
cell = new HtmlTableCell();
cell.InnerText = item.familyName.ToString();
row.Cells.Add(cell);
}
foreach (var givenName in item.givenName)
{
cell = new HtmlTableCell();
cell.InnerText = item.givenName.ToString();
row.Cells.Add(cell);
}
table.Rows.Add(row);
}
this.Controls.Add(table);
When I step through the debugger I can see that row.Cells.Add(cell) contains the family name in the first loop and given name in the second loop but then something seems to be wrong and I can't get the table to show up on the page with this data.
When I check the table.rows.add(row) it says that
base {System.SystemException} = {"'HtmlTableRow' does not support the InnerText property."}
What am I doing wrong here?
I've stepped through your code and I can't replicate the error you mention.
It's difficult to say for sure without seeing your data structure Name but a couple of observations:
I. If familyName is a string, your inner foreach will execute once for each character in the string. This may not be what you want as it'll output a surname x number of times where x = surname.length.
This will result in unequal numbers of table cells per row unless all your surnames are the same length.
So I would say get rid of the
foreach(var familyName in item.familyName){...}
loop and just leave the code inside so it'll output surname just once.
II. I'm guessing that item.givenName is an array or collection e.g. List<> of strings? If so you could just use
cell.InnerText = givenName;
Note that this is will still give you uneven numbers of table cells per row because people have different numbers of forenames ;-)
Having said that you really ought to use the built in controls for doing this kind of thing - the Repeater is probably the way to go.
E.g.
Markup
<asp:Repeater runat="server" id="rptNames" onItemDataBound="rptName_ItemDataBound" >
<HeaderTemplate>
<table>
<tr>
<td>Given Name(s)</td>
<td>Family Name</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("FamilyName") %></td>
<td>
<asp:Label runat="server" id="lGivenNames" />
</td>
</tr>
<ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
CodeBehind
Probably triggered by Page_Load - just bind your repeater to your Name collection:
rptNames.DataSource = Name;
rptNames.DataBind();
To output the GivenNames you use the ItemDataBound event which gets called for each row of the repeater:
protected void rptNames_ItemDataBound(object sender, RepeaterItemEventArgs e){
//Not interested the Header and Footer rows
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem){
Label l = ((Label)e.Item.FindControl("lGivenNames"));
string[] arrGivenNames = ((FullName)e.Item.DataItem).GivenNames;
foreach (string n in arrGivenNames){//could use a StringBuilder for a performance boost.
l.Text += n + " "; //Use a regular space if using it for Winforms
}
//For even slicker code, replace the Label in your repeater with another repeater and bind to that. Google `nested repeater` for a how to.
}
}
HTH.
Full Code
<h2>Doing it by hand - manually building up an HTML Table</h2>
<asp:Panel runat="server" ID="pnl1">
</asp:Panel>
<h2>With a Repeater</h2>
<asp:Repeater runat="server" id="rptNames" onItemDataBound="rptName_ItemDataBound" >
<HeaderTemplate>
<table border="1" style="border-color:Red;">
<tr>
<td>Given Name(s)</td>
<td>Family Name</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("FamilyName") %></td>
<td>
<asp:Label runat="server" id="lGivenNames" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace Testbed.WebControls
{
internal class FullName{
public string FamilyName{get;set;}
public string[] GivenNames{get;set;}
public FullName(){
}
public FullName(string[] _givenNames, string _familyName)
{
FamilyName = _familyName;
GivenNames = _givenNames;
}
}
public partial class HTMLTables : System.Web.UI.Page
{
List<FullName> Name;
protected void Page_Load(object sender, EventArgs e)
{
this.Name = new List<FullName>();
Name.Add(new FullName(new string[]{"Kylie"},"Minogue"));
Name.Add(new FullName(new string[]{"Angelina", "Kate", "Very-Lovely"}, "Jolie"));
Name.Add(new FullName(new string[]{"Audrey", "Veronica"},"Hepburn"));
HtmlTable table = new HtmlTable();
table.Border = 1;
HtmlTableRow row;
HtmlTableCell cell;
row = new HtmlTableRow();
cell = new HtmlTableCell();
cell.InnerText = "Given Name";
row.Cells.Add(cell);
cell = new HtmlTableCell();
cell.InnerText = "Family Name";
row.Cells.Add(cell);
foreach (var item in Name)
{
row = new HtmlTableRow();
//foreach (var familyName in item.FamilyName){
cell = new HtmlTableCell();
cell.InnerText = item.FamilyName.ToString();
row.Cells.Add(cell);
//}
foreach (string givenName in item.GivenNames)
{
cell = new HtmlTableCell();
cell.InnerText = givenName.ToString();
row.Cells.Add(cell);
}
table.Rows.Add(row);
}
this.pnl1.Controls.Add(table);
//Or do it with a repeater
rptNames.DataSource = Name;
rptNames.DataBind();
}
//This gets called everytime a data object gets bound to a repeater row
protected void rptName_ItemDataBound(object sender, RepeaterItemEventArgs e){
switch(e.Item.ItemType){
case ListItemType.Item:
case ListItemType.AlternatingItem:
string[] arrGivenNames = ((FullName)e.Item.DataItem).GivenNames;
foreach(string n in arrGivenNames){
((Label)e.Item.FindControl("lGivenNames")).Text += n + #" ";
}
break;
default:
break;
}
}
}
}