How to implement search functionality with repeater? - asp.net

I have an aspx page like this:
<asp:TextBox ID="SearchInput" AutoPostBack="true" runat="server" />
<asp:Repeater ID="SelectUserListItemRepeater" runat="server">
<ItemTemplate>
<div><%# DataBinder.Eval(Container.DataItem, "Title")%></div>
</ItemTemplate>
</asp:Repeater>
And code behind like this.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Test : UserControl
{
private IList<TestItem> items;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
items = new List<TestItem>();
items.Add(new TestItem { Title="Lars"});
items.Add(new TestItem { Title = "Johan" });
items.Add(new TestItem { Title = "Bob" });
SelectUserListItemRepeater.DataSource = items;
SelectUserListItemRepeater.DataBind();
SearchInput.TextChanged += new EventHandler(SearchInput_TextChanged);
}
void SearchInput_TextChanged(object sender, EventArgs e)
{
var input = sender as TextBox;
var searchResult = items.Where(i => i.Title.Contains(input.Text));
/* Here I would like to show this search result in the Repeater,
* but what is the best way to do it?
*/
}
}
public class TestItem {
public string Title { get; set; }
}
What is to best way to implement search functionality in this kind of situation? I have one search text input and one repeater which renders a list of strings in DIV elements. When user writes some search key in a input then the repeater should only show those strings which contains the search key? How can I hide other RepeaterItems which doesn't contains the search key? or should I remove those RepeaterItems some how?

Try this:
void SearchInput_TextChanged(object sender, EventArgs e)
{
var input = sender as TextBox;
var searchResult = items.Where(i => i.Title.Contains(input.Text));
SelectUserListItemRepeater.DataSource = searchResult;
SelectUserListItemRepeater.DataBind();
}

Try this
private static List<TestItem> items = new List<TestItem>();
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
items = new List<TestItem>();
items.Add(new TestItem { Title="Lars"});
items.Add(new TestItem { Title = "Johan" });
items.Add(new TestItem { Title = "Bob" });
SearchInput.TextChanged += new EventHandler(SearchInput_TextChanged);
// bind repeater.
BindRepeater();
}
protected void SearchInput_TextChanged(object sender, EventArgs e)
{
var input = sender as TextBox;
items = items.Where(i => i.Title.Contains(input.Text)).ToList();
BindRepeater();
}
private void BindRepeater()
{
SelectUserListItemRepeater.DataSource = items;
SelectUserListItemRepeater.DataBind();
}

Related

Get click event from linkbutton in compositecontrol in Web Forms

I have created a composite control which houses a number of tiles (which are also custom controls). In my web page I want to catch the click-event of a tile, but I can't figure out how.
This is the TileButton: (the components can be designed dynamically, but I left this part out to keep it simple)
public class TileButton : LinkButton
{
public string Title { get; set; }
public string ImageUrl { get; set; }
private System.Web.UI.WebControls.Label title =
new System.Web.UI.WebControls.Label();
private Image image = new Image();
protected override void CreateChildControls()
{
base.CreateChildControls();
title.Text = Title;
image.ImageUrl = ImageUrl;
Controls.Add(title);
Controls.Add(image);
}
protected override void RenderContents(HtmlTextWriter writer)
{
RenderTitle(writer);
RenderImage(writer);
}
private void RenderImage(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Class,
"some css classes");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
image.RenderControl(writer);
writer.RenderEndTag();
}
private void RenderTitle(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Class,
"other css classes");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.AddAttribute(HtmlTextWriterAttribute.Class,
"title css classes");
writer.RenderBeginTag(HtmlTextWriterTag.H6);
title.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
}
}
This is the composite control:
public class TilesControl : CompositeDataBoundControl
{
public List<TileButton> TileButtons { get; set; } =
new List<TileButton>();
protected override int CreateChildControls(IEnumerable datasource, bool databinding)
{
base.CreateChildControls();
int count = 0;
foreach (var item in datasource)
{
var tileButton = item as TileButton;
tileButton.ID = "tile" + count;
Controls.Add(tileButton);
TileButtons.Add(tileButton);
count++;
}
return count;
}
protected override void Render(HtmlTextWriter writer)
{
AddAttributesToRender(writer);
writer.AddAttribute(HtmlTextWriterAttribute.Class, "some css classes");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
foreach (var tile in TileButtons)
{
tile.CssClass = "button css classes";
tile.RenderControl(writer);
}
writer.RenderEndTag();
}
}
And in the page it's included like this:
<Something:TilesControl runat="server" ID="tiles1" DataSourceID="source1"></Something:TilesControl>
It all renders perfectly, the datasource is bound, but now I want the code behind to do something when a tileButton is clicked.
Extra: I would like the TileButton to have a property that defines WHAT to do when the button is clicked (some type of delegate?). Any pointers on that?
Thanks a lot.
It looks like you are binding a List<TileButton> as the DataSource of TilesControl. So you can bind a Click event to one of those buttons in the List before you bind them as the DataSource.
protected void Page_Load(object sender, EventArgs e)
{
//create a new tilescontrol instance
TilesControl tc = new TilesControl();
//create a list of tilebuttons
List<TileButton> buttons = new List<TileButton>();
//add some buttons for testing
for (int i = 0; i < 10; i++)
{
TileButton b = new TileButton();
b.ID = "TileButton" + i;
b.Title = "TileButton " + i;
//add the click event of a button here
b.Click += TileButton_Click;
//add the button to the list
buttons.Add(b);
}
//bind the list of buttons to the tilescontrol
tc.DataSource = buttons;
tc.DataBind();
//add the tilescontrol to the page
PlaceHolder1.Controls.Add(tc);
}
private void TileButton_Click(object sender, EventArgs e)
{
//display results
Label1.Text = ((TileButton)sender).Title + " Clicked!";
}

drop-down list in C# issue

drop-down list in C#.net not showing the items it supposed to show!
i hv a drop-down list that suppose to show image names from a folder, but it is not doing that!
i dont have errors when launching the .aspx file!
buuuuuut when i get output there is only empty dropdown list!
this the ManageProducts.aspx codes are:
Name:
Type:
" SelectCommand="SELECT * FROM [ProductTypes] ORDER BY [Name]">
Price:
Image:
Description:
and this the behind codes:
using System;
using System.Collections;
using System.IO;
public partial class PagesNew_ManagementPages_ManageProducts : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack) //this baby makes the data not come every time the pg is refreshed ,
//postback=refresh page
GetImages();
}
private void GetImages()
{
try
{
//get all filepaths
string[] images = Directory.GetFiles(Server.MapPath("~/Img/Products/"));
//get all filenames and put them in a stupid array....yeah DSA days
ArrayList imageList = new ArrayList();
foreach (string image in images)
{
string imageName = image.Substring(image.LastIndexOf(#"\", StringComparison.Ordinal) + 1);
imageList.Add(imageName);
// see the Array in dd viwe datasource and refresh
ddImage.AppendDataBoundItems = true;
ddImage.DataBind();
}
}
catch (Exception e)
{
lblResult.Text = e.ToString();
}
}
protected void ddImage_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
You want to bind your datalist outside of the for loop.
ArrayList imageList = new ArrayList();
foreach (string image in images)
{
string imageName = image.Substring(image.LastIndexOf(#"\", StringComparison.Ordinal) + 1);
imageList.Add(imageName);
}
ddImage.DataSource = imageList;
ddImage.AppendDataBoundItems = true;
ddImage.DataBind();

ASP NET: Is it possible to set control property dynamically?

On my aspx page has a button. I want to change its property dynamically.
For example:
A button which ID is Button1 and I want to change its property Visible to false.
On code behind have three variables hidefield = "Button1", property = "Visible" and value = false.
Is it possible to set the property Visible using the variables?
aspx:
<asp:Button ID="Button1" runat="server" Text="Button1" />
code behind:
protected void Page_Load(object sender, EventArgs e)
{
string hidefield = "Button1";
string property = "Visible";
bool value = false;
if (!IsPostBack)
{
Control myControl1 = FindControl(hidefield);
if (myControl1 != null)
{
myControl1.property = value; // <- I know this statement has error. Is there any way to set the property like this?
}
}
}
Using reflection, based on Set object property using reflection
using System.Reflection;
protected void Page_Load(object sender, EventArgs e)
{
string hidefield = "Button1";
string property = "Visible";
bool value = false;
if (!IsPostBack)
{
Control myControl1 = FindControl(hidefield);
if (myControl1 != null)
{
myControl.GetType().InvokeMember(hidefield ,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
Type.DefaultBinder, myControl, value);
}
}
}
It's pretty messy and not very human readable so therefore could have maintainablility issues.
how about this:
Button myControl1 = FindControl(hidefield) as Button;
if (myControl1 != null)
{
myControl1.Visible= value;
}
protected void Page_Load(object sender, EventArgs e)
{
string hidefield = "Button1";
string property = "Visible";
bool value = false;
if (!IsPostBack)
{
/* Use below two lines if you are using Master Page else you wouldnot be able to access your control */
ContentPlaceHolder MainContent = Page.Master.FindControl("MainContent") as ContentPlaceHolder;
Control myControl1 = MainContent.FindControl(hidefield);
if (myControl1 != null)
{
myControl1.GetType().GetProperty(property).SetValue(myControl1,value,null);
}
}
}

How to bind a List<string> to GridView in ASP.NET?

I am hitting an API and storing the returned parsed data to a List. Currently I am displaying the data in the ListView.
I am not able display the same list in a GridView. Can anyone guide me how to do it?
This is my aspx.cs code:
protected void Page_Load(object sender, EventArgs e)
{
ComodityList obj_comodity_in = (ComodityList)Session["comodity_list"];
Label1.Text = obj_comodity_in.status_code;
Label2.Text = obj_comodity_in.count.ToString();
//ComodityList obj_comodity_in = (ComodityList)Session["comodity_list"];
List<String> commodity_names = null;
getComodityNames(out commodity_names, obj_comodity_in);
ListView1.DataSource = commodity_names;
ListView1.DataBind();
}
private void getComodityNames(out List<String> commodity_names, ComodityList cl)
{
commodity_names = new List<string>();
foreach (Commodity c in cl.data)
{
commodity_names.Add(c.commodity);
commodity_names.Add(c.state);
commodity_names.Add(c.market);
commodity_names.Add(c.Maximum_Price.ToString());
commodity_names.Add(c.Minimum_Price.ToString());
commodity_names.Add(c.Modal_Price.ToString());
commodity_names.Add(c.origin);
commodity_names.Add(c.unit);
commodity_names.Add(c.variety);
}
}
Set AutoGenerateColumns property to true will help you.
Default.aspx:
<asp:GridView ID="GridView1" runat="server" Width="95%" autogeneratecolumns = "false">
Default.aspx.cs:
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
List<string> s = new List<string>() { "a", "b", "c" };
this.GridView1.DataSource = s;
this.GridView1.DataBind();
}
}
If you don't want to change the API (you still want to return a list of strings) and need to use a grid you could create a new class containing the properties you already had in Commodity and simply rehydrate the class using the lists string data. Each new 'Commodity' class could go in a new List<Commodity> and you can bind that to the grid.
On the other hand - it's probably better to reconsider what you are actually trying to achieve and then redesign the API if that is an option.

asp.net web forms best practice to retrieve dynamic server control values

I populate web form with dynamic list of exams from database. I want user to enter examination marks for each exam. There is list of exam titles and textbox near each title.
I create list with repeater control (ViewState is disabled) :
<asp:Repeater ID="rptExams" runat="server" onitemdatabound="rptExams_ItemDataBound" >
<ItemTemplate>
<tr>
<td>
<asp:Literal runat="server" ID="ltTitle"/>
</td>
<td>
<asp:HiddenField runat="server" ID="hfId"/>
<asp:Textbox runat="server" ID="tbMark"/>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
And bind data to repeater on page_init:
class Exam
{
public int Id { get; set;}
public string Title { get; set;}
}
...
// this list is retrieved from database actually
Exam[] Exams = new Exam[]
{
new Exam { Id = 1, Title = "Math"},
new Exam { Id = 2, Title = "History"}
};
...
protected void Page_Init(object sender, EventArgs e)
{
rptExams.DataSource = Exams;
rptExams.DataBind();
}
So far so good. Then I have to retrieve data on postback. I have two ways but both of them looks ugly.
Idea is to store dynamically created databounded controls on ItemDataBoundEvent in Page_Init stage, and process their values in Page_Load stage. It looks like this:
private Dictionary<HiddenField, TextBox> Id2Mark = new Dictionary<HiddenField, TextBox>();
protected void rptExams_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
...
if (IsPostBack)
{
var tbMark = (TextBox)e.Item.FindControl("tbMark");
var hfId = (HiddenField)e.Item.FindControl("hfId");
// store dynamically created controls
Id2Mark.Add(hfId, tbMark);
}
...
}
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
foreach (var pair in Id2Mark)
{
int examId = Int32.Parse(pair.Key.Value);
string mark = pair.Value.Text;
// PROCESS
}
...
I'm completely sure there is a better way to retrieve data from dynamically created controls. Thank you in advance!
Here's how you can do it:
First, don't rebind the data on postback - it's not necessary. Only bind it on the first call of the page.
protected void Page_Init(object sender, EventArgs e)
{
if (!IsPostBack){
rptExams.DataSource = Exams;
rptExams.DataBind();
}
}
You won't need the Dictionary neither.
Then, on a postback, you can get to the bound data as follows:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
foreach (RepeaterItem item in rptExams.Items)
{
HiddenField hfId = item.FindControl("hfId") as HiddenField;
TextBox tbMark = item.FindControl("tbMark") as TextBox;
int examId = Int32.Parse(hfId);
string mark = tbMark.Text;
// PROCESS
}
}
}

Resources