Select from db, making icons from the items - c#

What I'm trying to do is basicly what this photo shows.
When I select something from the treeview it passes a parameter to a linq command that selects some data from the database. For every item in the selection I want to make a Icon and a text that represents if the item is a folder or a file.
When I push the Icon or the Link i want it to do the same as i would push the treeview, pass a parameter to a linq command that selects again from the database and populates the placeholder.
The way I'm doing this now is to make at runtima a Panel that holds the ImageButton and LinkButton. Then i add the Panel to the ContentPlaceHolder.
The problem with this that it does it every time i select something new and also i cant get it to work if the push the icon or the linkbutton, only the from the treeview.
Could i use some controller and css to get this look for the Icons ?
Is there another better way ?
This is basicly the same system as the Explorer uses in Windows, Treeview shows only the folder but the window shows the folders and files. When i click a folder that folder opens up and the main window is populated with items that are inside that folder. If i click a file a editor opens up with the contents of the file.

Not sure I understand you question 100% but I think I got the gist.
I'm assuming that you want the folders first, then the files. I would create two repeaters in this area, one to hold the Folder Image and link buttons, and the other for the file image and link buttons.
Break your linq command into two queries, one to get the folders and one for files. Then just bind the repeaters to the corresponding repeaters.
Here's a bit of code to get you started:
<asp:Repeater ID="rptFolders" runat="server" OnItemCommand="rptFolders_ItemDataBound">
<ItemTemplate>
<div>
<asp:ImageButton ID="btnImage" runat="server" />
<asp:LinkButton ID="btnLink" runat="server" />
</div>
</ItemTemplate>
</asp:Repeater>
And the code behind after calling DataBind():
protected void rptFolders_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Book book = (Book)e.Item.DataItem; //Or whatever your passing
ImageButton btnImage = e.Item.FindControl("btnImage");
LinkButton btnLink = e.Item.FindControl("btnLink");
btnLink.Text = book.Name;
btnLink.Click += new EventHandler(FolderClicked);
btnImage.Click += new ImageClickEventHandler(FolderClicked);
}
}
You can obviously do whatever you want with Click Events, just added those in for good measure.
I would probably create a Folder and File Control and use those instead of the imagebutton / linkbutton combo, this way I could store more information about the Folder / File to access them later without having to do another query to get the ID or what not. But there are a million approaches to this, pick the one you think is best.
Let me know if you need more guidance w/ this solution, or if I didn't understand your question.
Happy Coding...

Sorry had to add as another Answer. Here's a quick sample of the folder user control.
Create your Control... Format however you want.
<%# Control Language="C#" AutoEventWireup="true" CodeFile="FolderButton.ascx.cs" Inherits="FolderButton" %>
<div>
<asp:ImageButton ID="btnImage" runat="server" ImageUrl="yourfolder.jpg" />
<asp:LinkButton ID="btnTitle" runat="server" />
</div>
Add Properties and Click Event to the Code Behind (don't forget to fire the click event when your image and link buttons are clicked):
public partial class FolderButton : System.Web.UI.UserControl
{
public int DatabaseId { get; set; }
public string Name { get; set;} // you can even set your linkbutton text here.
public event EventHandler Click;
}
Create your Repeater of the FolderButton Controls:
<asp:Repeater ID="rptFolders" runat="server" OnItemDataBound="rptFolders_ItemDataBound">
<ItemTemplate>
<uc1:FolderButton ID="FolderButton1" runat="server" />
</ItemTemplate>
</asp:Repeater>
Set Folder Id on DataBinding:
protected void rptFolders_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Book book = (Book)e.Item.DataItem; //Or whatever your passing
FolderButton btnFolder = e.Item.FindControls("FolderButton1");
btnFolder.Name=book.Name;
btnFolder.DatabaseId=book.Id;
btnFolder.Click += new EventHandler(FolderClicked);
}
}
Lastly you can then do whever you want on the event Click:
void FolderClicked(object sender, EventArgs e)
{
int id = ((FolderButton)sender).DatabaseId;
/// Do something with your Id
}
Let me know if anything is unclear. This is just a quick freehand sample, so forgive any typos or bad practices... code is just for demostration purposes only.

Related

How to access specific controls in a ASP.Net Repeater

Introduction
I am working on a college project where I need to build a shopping website.
I am currently building a "Manage Shopping Cart" page with the following structure:
What is important for my question is the "products". The "products" is a ASP.Net Repeater that only uses the ItemTemplate control. The repeater is then populated with a list of products in a user's cart.
What is my problem?
The particular area I am having trouble with is the "Save" Button.
The user can change the quantity of each product they want; however, they must click the "Save" button for the information to go to the database.
The trouble is accessing the correct quantity textbox inside my Save button's onclick event.
How can I access the correct text box in all of my Save button's OnClick Events?
What have I tried?
I was initially thinking of using the WebControl.FindControl method.
Of course though, the FindControl requires an ID and I would need different IDs for each textbox.
In order to the fix this ID problem, I tried...
firstly...
Tried binding the productId to the textbox id.
<asp:TextBox ID='quantity<%#Eval("productId") %>' runat="server" TextMode="Number" min="1" Text='<%#Eval("selectedQuantity") %>' max='<%#Eval("availableQuantity") %>' />
I then found out that is not is possible; because, when setting an ID this way, you must use "simple ids" (Example: "button1"). Supposedly I could set the ID in the code-behind though.
Secondly...
I then tried using the Repeater's OnItemCreated Event to dynamically set the ID of the TextBox to "quantityX", where X is an Product ID.
What I did in is bind the productId into a WebControl attribute:
<asp:TextBox ID='quantity' productId='<%#Eval("productId") %>' runat="server" TextMode="Number" min="1" Text='<%#Eval("selectedQuantity") %>' max='<%#Eval("availableQuantity") %>' />
After this, I then using the FindControl() method to get TextBoxs with an ID of "quantity". After finding the TextBox, I would take the productId attribute and append its value to the TextBox ID.
protected void productsList_ItemCreated(object sender, RepeaterItemEventArgs e)
{
if(e.Item.ItemType == ListItemType.Item)
{
TextBox quantity = (TextBox)e.Item.FindControl("quantity");
quantity.ID = String.Format("quantity{0}", quantity.Attributes["productId"]);
}
}
I then found out that the productId attribute did not have a value; because, the DataBinding has not occurred. In otherwords, Eval("productId") was not running.
thirdly...
I took the same approach as the one before with 1 difference. I used the Repeater's OnItemDataBound event instead of the OnItemCreated Event.
protected void productsList_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if(e.Item.ItemType == ListItemType.Item)
{
TextBox quantity = (TextBox)e.Item.FindControl("quantity");
quantity.ID = String.Format("quantity{0}", quantity.Attributes["productId"]);
}
}
This partially worked; however, there was one problem. The product with the biggest Product ID was skipped. (E.X, if I had products 4, 32, and 68. The Product ID of 68 would be skipped)
As you can see in the image below, we have 3 products. I edited some text the picture to clearly point out the TextBoxs (as they are rendered).
The IDs present are 1, 32 and 34. If you look at the ID attribute of 1 and 32, you will see they have "quantity" with their Product ID appended.
Now look at the ID attribute of 34. The ID attribute is only "quantity".
Now I am kinda of stuck.
What am I using?
Visual Studio 2017
.NET Framework 4.6.1
2-Tier WebForms Project
Google Chrome
To get text from textbox in your save button click use below code:
// get item on where button is clicked
RepeaterItem item = (RepeaterItem)((Button) sender).NamingContainer;
// get correct textbox from the item
TextBox txtQuantity = (TextBox)item.FindControl("quantity");
string qtyText = txtQuantity.Text;
In your third approach your're only checking DataItems but you have to check it on AlternatingItems also:
if (e.ItemType == ListItemType.Item || e.ItemType == ListItemType.AlternatingItem)

ASP.NET populate lists referencing each other on selected index change

I have an ASP.NET control with three listboxes: LBParent, LBChild1 and LBChild2.
LBParent has to be filled programmatically. I do this in Page_Load.
When the user selects a value in LBParent, I want to fill both LBChild1 and LBChild2 with some data, programmatically. The children lists must also keep track of their selected value.
Basically, the parent list is a list of users, the first list is a list of permissions the user has, the second list is a list of permissions the user doesn't have.
My plan is to add two buttons to move permissions between the two lists.
Unfortunately, I cannot get this to work properly.
If I populate the parent list in Page_Load, the selected index seems to reset. I used ViewState to save the index... but this seems to require an additional refresh, because it doesn't update after the PostBack. This is not acceptable.
If I populate the children listboxes on the OnParentSIC event, there is no way I can keep track of their selected index. The OnChildXSIC events never fire, because the listboxes get repopulated "too soon". (?)
How can I get this to work as intended? Maybe there is a better solution but I'd really like to understand how to get this solution to work, as I can't see a possible solution at the moment.
Control.ascx
<%# Control Language="C#" AutoEventWireup="true" EnableViewState="True" CodeBehind="..." Inherits="..." %>
<form runat="server">
<asp:ListBox ID="LBParent" runat="server" CssClass="form-control"
AutoPostBack="true" OnSelectedIndexChanged="OnParentSIC" />
<asp:ListBox ID="LBChild1" runat="server" CssClass="form-control"
AutoPostBack="true" OnSelectedIndexChanged="OnChild1SIC" />
<asp:ListBox ID="LBChild2" runat="server" CssClass="form-control"
AutoPostBack="true" OnSelectedIndexChanged="OnChild2SIC" />
</form>
Control.ascx.cs
protected void Page_Load(object sender, EventArgs e)
{
// Populate parent
for(...) LBParent.Items.Add(...);
}
The Onchange-event fires, but before that the OnLoad fires.
So:
The user clicks on an selection
A postback is triggered
At the server the Onload fires (and rebuilds the list)
The OnSelectedIndexChanged fires (which lost the selection by now)
So I would try to save the current-selected-index before you rebuild the list (in the Onload).
If you restore it later on while you are in the same 'postback' you can save it in a simple variable. No need to store in a Viewstate or Session.
use Like this
If You are on the Same Page then You can Use ViewState/Hidden Fields
to Maintain States
First Time Adding ListItem on PageLoad Use Like this
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
AddListItems();
}
}
Protected Void AddListItems()
{
// Populate parent
for(...) LBParent.Items.Add(...);
for(...) SecondList.Items.Add(...);
for(...) ThirdList.Items.Add(...);
}

How to make GridView take me to a different page

I;m new on SO so please be gentle. I searched and didn't find what I was looking for.
My problem is as follows - I am making a game for Windows Store where you must finish sentences based on the animation you see below the sentence. The game will offer many stories and this is my problem. I used the default GridView template to create the MENU for picking your stories. And this is where I am stuck:
How to tell the app using json that when clicked it should open a specific page (the wanted level)?
This is the code that I need to change probably:
void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
// Navigate to the appropriate destination page, configuring the new page
// by passing required information as a navigation parameter
var itemId = ((SampleDataItem)e.ClickedItem).UniqueId;
this.Frame.Navigate(typeof(ItemDetailPage), itemId);
}
I know that I need to change the last line so that it takes some information from the json file and changes it for a specific page file name from the solution.
I hope that you understand what I mean :(
Use the template field to add a button with your routing argument.
<asp:TemplateField HeaderText="Action">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" Text="Action" CommandName="Action"
CommandArgument='<%#Bind("ID ") %>'></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
Code Behind:
protected void Gridview1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Action")
{
string ID = e.CommandArgument; // Do something with it.
}

executing a repeater item server side

I have a list of asp:LinkLabels which are contained a repeater.
I have a button that says "Get Started" when a user clicks on this button, I want it to execute the first item in the repeater.
I have this code working fine in Chrome, but not in any other browser:
<asp:Button ID="SubmitInfo" runat="server" Text="Save and Get Started" Width="218px" OnClientClick="__doPostBack('rptList$ctl01$Label15','')" CssClass="submit-button-huge" OnClick="SubmitInfo_Click" />
Is there a way to do this server side without using the __doPostBack javascript?
Is there anything glaringly wrong here?
Difficult to answer without your whole code. I'll assume your LinkLabels are LinkButtons named "lb1", and you use commandName and CommandArgument, Repeater_ItemCommand
I would try something like this in the repeater.ItemCreated
private void Repeater_ItemCreated(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
if(e.Item.ItemType==ListItemType.Item || e.Item.ItemType==ListItemType.AlternatingItem)
{
var lb = (LinkButton)e.Item.FindControl("lb1");
if(IsPostBack && e.Item.ItemIndex==0)
{
SubmitInfo.Click+= (source,args)=>Repeater_ItemCommand(lb,new RepeaterCommandEventArgs(e.Item,lb,new CommandEventArgs(lb.CommandName,lb.CommandArgument)));
}
...
Hope this will help

how to Manage UserControl dynamically on a page....?

my scenerio is like this,
i have to make a admin page ( header section ) in which i have to select single or multiple User Control from my dropdownlist ....
which will be added in the page dynamically ....
how should i do it ?
currently my idea is like this
when a some one selects and add a usercontrol from the dropdownlist list , i will add usercontrols tags in a textarea and save it in db ...
and when index pages of website is called then header section will be rendered from database and displayed ..
but how should i manage control tag which should be place on the top of the page in index.aspx while rendering it ??
please i know at some point it would be difficult to understand but i will try my best to reply if you have any query related to my question
take care
If i get your question correctly there is no need to store tags or anything in databse. Just the name and path of control (remember User Controls can only be loaded from same project) that you wana load.
Here is the code sample to load a user control dynamically.
<asp:DropDownList ID="userControlSelection" runat="server" AutoPostBack="true"
onselectedindexchanged="userControlSelection_SelectedIndexChanged">
<asp:ListItem Value="1">User Control One</asp:ListItem>
<asp:ListItem Value="2">User Control Two</asp:ListItem>
</asp:DropDownList>
<asp:Panel ID="controlHolder" runat="server" ></asp:Panel>
And in the code behing the important part is "this.LoadControl("~/WebUserControl2.ascx");" Look at this article for more info and loading user controls Dynamically creating User Controls
protected void userControlSelection_SelectedIndexChanged(object sender, EventArgs e)
{
Control c = null;
if (userControlSelection.SelectedValue == "1")
{
c = this.LoadControl("~/WebUserControl1.ascx");
}
else if (userControlSelection.SelectedValue == "2")
{
c = this.LoadControl("~/WebUserControl2.ascx");
}
if (c != null)
{
controlHolder.Controls.Clear();
controlHolder.Controls.Add(c);
}
else
{
//Throw some error
}
}
Hope this helps, Thanks

Categories

Resources