I created a 2D array Board, holding objects of GameCell.
Default.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link rel="stylesheet" href="includes/css/style.css" />
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>ארבע בשורה</h1>
<div id="Board">
<asp:Label ID="Label1" runat="server"></asp:Label>
<asp:PlaceHolder ID="MyBoard" runat="server" />
</div>
</div>
</form>
</body>
</html>
Default.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
Game.CreateControls();
}
protected void Page_Init(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
Game.Set(MyBoard, Label1);
Game.Reset();
}
}
GameCell.cs:
public class GameCell : ImageButton
{
public Position Position; // Justs holds the properties of Row and Col
public CellType Type;
public GameCell(Position Pos)
{
this.Position = new Position(Pos);
this.Type = CellType.Empty;
}
}
Game.cs:
public class Game
{
public const int R = 6;
public const int C = 9;
public static GameCell[,] Board;
public static PlaceHolder Holder;
public static Label Log;
public static CellType CurrentType;
public static string[] Images = new string[] { "red", "empty", "blue" };
public static void Set(PlaceHolder Holder, Label Log)
{
Game.Reset();
Game.Holder = Holder;
Game.Log = Log;
}
public static void CreateControls()
{
for (int i = 0; i < Game.R; i++)
{
for (int j = 0; j < Game.C; j++)
{
Game.Board[i, j].ImageUrl = Game.ImageUrlByType(Game.Board[i, j].Type);
Game.Board[i, j].ID = i + "_" + j;
Game.Board[i, j].Click += new ImageClickEventHandler(Image_Click);
Game.Holder.Controls.Add(Game.Board[i, j]);
}
}
}
public static void Image_Click(object sender, EventArgs e)
{
int row = 0;
int col = int.Parse(((GameCell)sender).ID[2].ToString());
if (Game.Board[row, col].Type == CellType.Empty)
{
while (row < Game.R - 1 && Game.Board[row, col].Type == CellType.Empty)
{
row++;
}
Game.SetImage(row, col);
Game.CurrentType = (CellType)(-(int)Game.CurrentType);
Log.Text = col + " " + row + " " + Game.CurrentType;
Game.Board[row, col].Enabled = false;
}
}
public static void SetImage(int r, int c)
{
Game.Board[r, c].Type = Game.CurrentType;
Game.Board[r, c].ImageUrl = Game.ImageUrlByType(Game.CurrentType);
}
public static void Reset()
{
Game.Board = new GameCell[R, C];
Game.CurrentType = CellType.Blue;
for (int i = 0; i < Game.R; i++)
{
for (int j = 0; j < Game.C; j++)
{
Game.Board[i, j] = new GameCell(new Position(i, j));
}
}
}
public static string ImageUrlByType(CellType t)
{
return "includes/images/" + Game.Images[(int)t + 1] + ".png";
}
}
The controls are rendered, and are clickable when first launching the project, but after I do click one of them, no controls are added to my Holder (MyBoard).
Why is this happening?
Edit:
I found the solution. passing MyBoard as an argument to CreateControls did it. Maybe the reference wasn't reliable anymore (I saved it in an object) after page_load.
Every time your Page_Load is called, you recreate your controls. They are stored in static members, which means that all users of this web site share a common board. Is this really what you want? Would it not be better to store the Game in the Session? (of course I don't know your requirements, but I always try to avoid static members in web applications).
A possible solution could be to check whether it is not a postback, before you recreate the controls.
if (!IsPostback)
{
}
Related
While coding an assignment I've come to need to transfer data from the code-behind to the view so that I can parse that data with Javascript and build some HTML with it, and I've decided to use asp:HiddenField to that end.
However, it seems something goes wrong, since I get the error "The name "HiddenFieldData" does not exist in the current context".
I assume that I'm somehow not linking the view to the model correctly.
Perhaps it's because I'm using a model that is not the appropriate cshtml.cs, but one that is "given" to the view via the controller.
Truth be told, this is my first time with ASP.NET so it's very likely the problem is somewhere here.
The code in question, I've marked the trouble spots with '>>>>':
Controller -
public class saveController : Controller
{
// GET: Save
public ActionResult SaveRoute()
{
saveModel model = new saveModel();
Model given >>>> return View(model);
}
}
Model -
public class saveModel
{
private DataMiner miner;
public saveModel(string ip = "127.0.0.1", int port = 5400, int duration = 10, int interval = 1000)
{
// Initialize miner
miner = new DataMiner(ip, port, duration, interval);
}
public void SaveRoute()
{
// Mine and retrieve data
miner.Mine();
double[][] data = miner.GetData();
int lines = data.GetLength(0);
int cols = data.GetLength(1);
string[] str_data = new string[lines];
for (int i = 0; i < lines; ++i)
{
// Turn double data into strings to write
str_data[i] = data[i].ToString();
}
// Write to file
System.IO.File.WriteAllLines(#"file1.txt", str_data);
// Write values to HiddenField
string values = String.Join(" ", str_data);
Error here >>>> HiddenFieldData.Value = values;
// Call JS function to load at
ScriptManager.RegisterStartupScript(this, GetType(), "showDataMined", "showDataMined();", true);
}
}
View -
#model RESTful_Flight_Simulator.Models.saveModel
#{
ViewBag.Title = "SaveRoute";
}
<html>
<head>
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" />
<script type="text/javascript" language="javascript">
function showDataMined()
{
var body = document.body
var tbl = document.createElement('table');
tbl.style.width = '100px';
tbl.style.border = '1px solid black';
for (var i = 0; i < 3; i++)
{
var tr = tbl.insertRow();
for (var j = 0; j < 2; j++)
{
if (i == 2 && j == 1) { break; }
else
{
var td = tr.insertCell();
td.appendChild(document.createTextNode('Cell'));
td.style.border = '1px solid black';
if (i == 1 && j == 1) {
td.setAttribute('rowSpan', '2');
}
}
}
}
// Build title for table
var title = document.createElement('h3');
title.innerHTML = "Data mined:";
// Finally, append title and table to body
body.appendChild(document.createElement('hr'));
body.appendChild(title);
body.appendChild(tbl);
}
</script>
</head>
<body>
HiddenField >>>> <asp:HiddenField id="HiddenFieldData" runat="server" value="" />
<h2>Saving route...</h2>
</body>
</html>
Thanks ahead for any help!
I am binding Telerik RadTreeView from a Datatable. I want to expand the radTreeView nodes at root level (node.level=0) and their child only (node.level=1) from serverside.
Datatable contains a column which holds the value for node's level. But the radTreeView doesn't expand at all.
This is the code:
IList<RadTreeNode> allNodesBS = tvAssets.GetAllNodes();
for (int i = 0; i < allNodesBS.Count; i++)
{
RadTreeNode node = (RadTreeNode)allNodesBS[i];
string nodeLevel = dt.Rows[i]["bs_node_level"].ToString();
if (nodeLevel == "0" || nodeLevel == "1")
{
node.Expanded = true; //doesn't work
}
}
//tvAssets.ExpandAllNodes(); This works
tvAssets.ExpandAllNodes(); works but I don't want to expand all the nodes because it contains large number of nodes.
And I can't do it from clientside because it has some issues.
RadTreeView obj is null in JavaScript
Please try with the below code snippet. To bind data I have used programmatic data binding method but below code works for all binding.
ASPX
<head runat="server">
<title></title>
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<telerik:RadCodeBlock ID="RadCodeBlock1" runat="server">
<script type="text/javascript">
var IsTreeViewLoaded;
$(document).ready(function () {
IsTreeViewLoaded = setInterval(function () { test() }, 500);
});
function test() {
console.log("jayesh");
var treeView = $find("<%=RadTreeView1.ClientID%>")
if (treeView && treeView.get_allNodes()) {
clearInterval(IsTreeViewLoaded);
var nodes = treeView.get_allNodes();
for (var i = 0; i < nodes.length; i++)
if (nodes[i].get_level() == 0 || nodes[i].get_level() == 1) {
if (nodes[i]._hasChildren() == true) {
var parentnode = nodes[i];
parentnode.expand();
}
}
}
}
</script>
</telerik:RadCodeBlock>
</head>
<body>
<form id="form1" runat="server">
<div>
<telerik:RadScriptManager ID="RadScriptManager1" runat="server"></telerik:RadScriptManager>
<telerik:RadTreeView ID="RadTreeView1" runat="server" Width="300px" Height="350px">
</telerik:RadTreeView>
</div>
</form>
</body>
ASPX.CS
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Init(object source, System.EventArgs e)
{
}
protected void Page_Load(object sender, EventArgs e)
{
BindToIEnumerable(RadTreeView1);
}
internal class SiteDataItem
{
private string text;
private int id;
private int parentId;
public string Text
{
get { return text; }
set { text = value; }
}
public int ID
{
get { return id; }
set { id = value; }
}
public int ParentID
{
get { return parentId; }
set { parentId = value; }
}
public SiteDataItem(int id, int parentId, string text)
{
this.id = id;
this.parentId = parentId;
this.text = text;
}
}
private static void BindToIEnumerable(RadTreeView treeView)
{
List<SiteDataItem> siteData = new List<SiteDataItem>();
siteData.Add(new SiteDataItem(1, 0, "Products"));
siteData.Add(new SiteDataItem(2, 1, "Telerik UI for ASP.NET Ajax"));
siteData.Add(new SiteDataItem(3, 1, "Telerik UI for Silverlight"));
siteData.Add(new SiteDataItem(4, 2, "RadGrid"));
siteData.Add(new SiteDataItem(5, 2, "RadScheduler"));
siteData.Add(new SiteDataItem(6, 2, "RadEditor"));
siteData.Add(new SiteDataItem(7, 3, "RadGrid"));
siteData.Add(new SiteDataItem(8, 3, "RadMenu"));
siteData.Add(new SiteDataItem(9, 3, "RadEditor"));
siteData.Add(new SiteDataItem(10, 9, "RadEditor1"));
siteData.Add(new SiteDataItem(11, 9, "RadEditor1"));
treeView.DataTextField = "Text";
treeView.DataFieldID = "ID";
treeView.DataFieldParentID = "ParentID";
treeView.DataSource = siteData;
treeView.DataBind();
}
}
Let me know if any concern.
I'm trying to use an ajax panel to add keep multiple images added to table cells dynamically. Thing is when I add the second image, the first one dissapears.
Its really just a silly example to try and get ajax controls working for another project.
I'm putting an image of Bill Gates in row 3, column 3 and an image of Steve Jobs in row 1, column 5. I have a button to place each image.
I can't seem to get both to display at the same time.
I have written a function to generate the cell id (GenerateTableCellID), as I've been told I would need to to this. Also there is a function to extract the cell and row in a tuple (GetColumnAndRow).
I'm not sure how to use a Session object to save the data. I thought using AJAX would be the answer, though I think I'm missing a major aspect of it.
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<div id="tablePlaceHolder" runat="server"></div>
<asp:Button ID="tblButton2" runat="server" Text="Add Steve Jobs" OnClick="tblButton_Click_Jobs" />
<asp:Button ID="tblButton" runat="server" Text="Add Bill Gates" OnClick="tblButton_Click" />
</ContentTemplate>
</asp:UpdatePanel>
</asp:Content>
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Page_Init(object sender, EventArgs e)
{
int tableSize = 5;
var t = new HtmlTable();
t.ID = "myTable";
var placeHolderURL = "http://wiki.tripwireinteractive.com/images/4/47/Placeholder.png";
for (int r = 0; r < tableSize; r++)
{
var tableRow = new HtmlTableRow();
tableRow.ID = "row_" + r.ToString();
for (int c = 0; c < tableSize; c++)
{
var tableCell = new HtmlTableCell();
var id = GenerateTableCellID(r, c);
tableCell.ID = id;
tableCell.Height = "20";
tableCell.Width = "20";
tableCell.InnerHtml = string.Format("<img src='{0}' width='20' height='20' />", placeHolderURL);
tableRow.Controls.Add(tableCell);
}
t.Controls.Add(tableRow);
}
tablePlaceHolder.Controls.Add(t);
}
protected void tblButton_Click(object sender, EventArgs e)
{
int c =2;
int r = 2;
var id = GenerateTableCellID(c, r);
var image = GenerateImage("http://www.mnn.com/sites/default/files/billgates.jpg");
var cell = (HtmlTableCell)UpdatePanel2.FindControl(id);
cell.InnerHtml = "";
cell.Controls.Add(image);
}
protected void tblButton_Click_Jobs(object sender, EventArgs e)
{
int c = 4;
int r = 0;
var id = GenerateTableCellID(c, r);
var image = GenerateImage("http://images.boomsbeat.com/data/images/full/209/jobs-jpg.jpg");
var cell = (HtmlTableCell)UpdatePanel2.FindControl(id);
cell.InnerHtml = "";
cell.Controls.Add(image);
}
protected Image GenerateImage(string url)
{
var image = new Image();
image.ImageUrl = url;
image.Width = 20;
image.Height = 20;
return image;
}
protected string GenerateTableCellID(int c, int r)
{
return "column_" + c.ToString() + "_row_" + r.ToString();
}
protected Tuple<int, int> GetColumnAndRow(string tableCellID)
{
string[] splitString = tableCellID.Split('_');
int column, row;
if (Int32.TryParse(splitString[1], out column) && Int32.TryParse(splitString[3], out row))
{
return new Tuple<int, int>(column, row);
}
else
{
return null;
}
}
It is because at every update you clear the html present before by cell.InnerHtml = ""; remove this and try
protected void tblButton_Click_Jobs(object sender, EventArgs e)
{
int c = 4;
int r = 0;
var id = GenerateTableCellID(c, r);
var image = GenerateImage("http://images.boomsbeat.com/data/images/full/209/jobs-jpg.jpg");
var cell = (HtmlTableCell)UpdatePanel2.FindControl(id);
//cell.InnerHtml = "";
cell.Controls.Add(image);
}
As mentioned on the Page LifyCycle your table is created everytime when you do reload page (does not matter is this postback or not). Also you could read this post. In other words, it is not proper way store your data in the dynamic generated controls, because you lose your data on page load.
But if it is necessary for you could use AJAX methods ($.get and $.post, not UpdatePanel) to get data from the backend and add this to generated control on the client side
I am trying to extend the asp.net DataPager control into a custom control with predefined templates. This is the desired output
Problems:
When I load the page containing the custom DataPager for the first time, the SelectMethod of my ObjectDataSource is called 3 times.
When I try to load another page of data using the DataPager, the SelectMethod is called twice.
When I try to load another page of data, either by using the Next/Previous buttons or the DropDownList, the page does not change. I ran some debugging and found that it was not passing the correct value to the StartRowIndexParameter of the SelectMethod (it just passed 0 everytime it called the method).
Here's the code for my custom control.
public class DataPagerDDL : DataPager
{
protected override void RenderContents(HtmlTextWriter writer)
{
//add custom template
TemplatePagerField templateField = new TemplatePagerField();
templateField.PagerTemplate = new CustomTemplate();
Fields.Add(templateField);
//add previous/next page template
NextPreviousPagerField nextPreviousField = new NextPreviousPagerField();
nextPreviousField.ShowFirstPageButton = false;
nextPreviousField.ShowLastPageButton = false;
nextPreviousField.PreviousPageText = "<<";
nextPreviousField.NextPageText = ">>";
Fields.Add(nextPreviousField);
base.RenderContents(writer);
}
public void cmbPage_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList cmbPage = (DropDownList)sender;
this.SetPageProperties(cmbPage.SelectedIndex * MaximumRows, MaximumRows, true);
}
}
public class CustomTemplate : ITemplate
{
/// <summary>
/// Insert an instance of text and controls into the specified container.
/// </summary>
public void InstantiateIn(Control container)
{
DataPagerFieldItem caller = (DataPagerFieldItem)container;
DataPagerDDL pager = (DataPagerDDL)caller.Parent;
int totalPages = pager.TotalRowCount / pager.MaximumRows;
if (pager.TotalRowCount % pager.MaximumRows > 0) totalPages += 1;
int currentPage = (pager.StartRowIndex / pager.MaximumRows) + 1;
DropDownList cmbPage = new DropDownList();
cmbPage.ID = "cmbPage";
cmbPage.AutoPostBack = true;
cmbPage.SelectedIndexChanged += new EventHandler(pager.cmbPage_SelectedIndexChanged);
for (int i = 1; i <= totalPages; i++)
{
ListItem item = new ListItem(i.ToString(), i.ToString());
if (i == currentPage) item.Selected = true;
cmbPage.Items.Add(item);
}
pager.Controls.Add(new LiteralControl("Page "));
pager.Controls.Add(cmbPage);
pager.Controls.Add(new LiteralControl(" of " + totalPages.ToString() + " pages | "));
}
}
And this is what my page looks like:
<asp:ListView ID="ListView1" DataSourceID="ods1" ... >
...
</asp:ListView>
<custom:DataPagerDDL ID="CustomDataPager" runat="server" PagedControlID="ListView1"
PageSize="25">
</custom:DataPagerDDL>
<asp:ObjectDataSource ID="ods1" ... >
</asp:ObjectDataSource>
What should I do to make my custom DataPager work as intended? Thanks in advance! :)
I suspect you're creating the pager fields too late in the page lifecycle. Try creating them from the Init event of the DataPagerDDL class.
Also, your CustomTemplate should be adding the controls to the container, not the pager.
public class DataPagerDDL : DataPager
{
protected override void OnInit(EventArgs e)
{
CreateDefaultPagerFields();
base.OnInit(e);
}
protected virtual void CreateDefaultPagerFields()
{
//add custom template
TemplatePagerField templateField = new TemplatePagerField();
templateField.PagerTemplate = new CustomTemplate();
Fields.Add(templateField);
//add previous/next page template
NextPreviousPagerField nextPreviousField = new NextPreviousPagerField();
nextPreviousField.ShowFirstPageButton = false;
nextPreviousField.ShowLastPageButton = false;
nextPreviousField.PreviousPageText = "<<";
nextPreviousField.NextPageText = ">>";
Fields.Add(nextPreviousField);
}
public void cmbPage_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList cmbPage = (DropDownList)sender;
SetPageProperties(cmbPage.SelectedIndex * MaximumRows, MaximumRows, true);
}
}
public class CustomTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
DataPagerFieldItem caller = (DataPagerFieldItem)container;
DataPagerDDL pager = (DataPagerDDL)caller.Parent;
int totalPages = pager.TotalRowCount / pager.MaximumRows;
if (pager.TotalRowCount % pager.MaximumRows > 0) totalPages += 1;
int currentPage = (pager.StartRowIndex / pager.MaximumRows) + 1;
DropDownList cmbPage = new DropDownList();
cmbPage.ID = "cmbPage";
cmbPage.AutoPostBack = true;
cmbPage.SelectedIndexChanged += pager.cmbPage_SelectedIndexChanged;
for (int i = 1; i <= totalPages; i++)
{
ListItem item = new ListItem(i.ToString(), i.ToString());
if (i == currentPage) item.Selected = true;
cmbPage.Items.Add(item);
}
container.Controls.Add(new LiteralControl("Page "));
container.Controls.Add(cmbPage);
container.Controls.Add(new LiteralControl(" of " + totalPages + " pages | "));
}
}
Basically I want to implement a filtering option for a Grid view and I have a dropdown list containing the column names and a checkboxlist containing the available filtering values for that column. Every time I select a different column, I have to load the filtering values for that column into the checkbox list.
The problem I have is that when I change the column in the dropdown list, the event for the checklist is fired and the application crashes.
My controls are defined like this:
<div class="LeftAligned">
<asp:Label ID="FilterLabel" runat="server" Text="Filter by:" />
<asp:DropDownList runat="server" ID="FilterReviewsDropDownList" AutoPostBack="true" OnSelectedIndexChanged="FilterReviewsDropDownList_SelectedIndexChanged" />
<asp:ImageButton ID="FilterReviewsButton" runat="server" ImageUrl="~/images/filter.png" AlternateText="VALUE" CssClass="filter_button" OnClick="FilterReviewsButton_Click" />
<div onmouseout="javascript:bMouseOver=false;" onmouseover="javascript:bMouseOver=true;" class="filter_div">
<asp:CheckBoxList AutoPostBack="true" ID="FilterReviewsCheckBoxList" ClientIDMode="Static" runat="server" CssClass="filter_checklist collapsed"
OnSelectedIndexChanged="FilterReviewsCheckBoxList_Selected">
</asp:CheckBoxList>
</div>
<%--asp:Button runat="server" ID="ApplyFilterButton" Text="Apply Filter" OnClick="ApplyFilterButton_Click"/>
<asp:Button runat="server" ID="ClearFilterButton" Text="Clear Filter" OnClick="ClearFilterButton_Click"/--%>
</div>
In the CodeBehind file I have the following code:
protected void FilterReviewsButton_Click(object sender, EventArgs e)
{
FilterReviewsCheckBoxList.CssClass = "filter_checklist";
}
protected void FilterReviewsDropDownList_SelectedIndexChanged(object sender, EventArgs e)
{
LoadFilterCheckboxes(FilterReviewsDropDownList.SelectedIndex);
}
private void LoadFilterCheckboxes(int iColumn)
{
SortedSet<string> oItems = new SortedSet<string>();
for (int i = 0; i < ReviewsGridView.Rows.Count; i++)
{
IEnumerable<Label> oLabels = ReviewsGridView.Rows[i].Cells[iColumn].Controls.OfType<Label>();
string sValue = "";
if (oLabels != null && oLabels.Count() > 0)
{
sValue = oLabels.First().Text;
}
else
{
sValue = ReviewsGridView.Rows[i].Cells[iColumn].Text;
}
if (!oItems.Contains(sValue))
oItems.Add(sValue);
}
FilterReviewsCheckBoxList.Items.Clear();
FilterReviewsCheckBoxList.Items.Add("All");
FilterReviewsCheckBoxList.Items[0].Selected = true;
foreach (string sItem in oItems)
{
FilterReviewsCheckBoxList.Items.Add(sItem);
FilterReviewsCheckBoxList.Items[FilterReviewsCheckBoxList.Items.Count - 1].Selected = true;
}
}
protected void FilterReviewsCheckBoxList_Selected(object sender, EventArgs e)
{
string sResult = Request.Form["__EVENTTARGET"];
if (string.IsNullOrEmpty(sResult))
{
FilterReviewsCheckBoxList.Items[0].Selected = true; //weird bug fix...
return;
}
string[] sCheckedBox = sResult.Split('$');
//get the index of the item that was checked/unchecked
int i = int.Parse(sCheckedBox[sCheckedBox.Length - 1].Split('_')[1]);
if (i == 0)
{
if (FilterReviewsCheckBoxList.Items[i].Selected == true)
{
for (int j = 1; j < FilterReviewsCheckBoxList.Items.Count; j++)
FilterReviewsCheckBoxList.Items[j].Selected = true;
}
else
{
for (int j = 1; j < FilterReviewsCheckBoxList.Items.Count; j++)
FilterReviewsCheckBoxList.Items[j].Selected = false;
}
}
else
{
if (FilterReviewsCheckBoxList.Items[i].Selected == false)
{
FilterReviewsCheckBoxList.Items[0].Selected = false;
}
else
{
//if (oFirstTable != null)
//{
// oTable = oFirstTable;
// oView = oTable.DefaultView;
//}
bool bAllChecked = true;
for (int j = 1; j < FilterReviewsCheckBoxList.Items.Count; j++)
{
if (FilterReviewsCheckBoxList.Items[j].Selected == false)
{
bAllChecked = false;
break;
}
}
if (bAllChecked)
FilterReviewsCheckBoxList.Items[0].Selected = true;
}
}
}
Any idea of why FilterReviewsCheckBoxList_Selected is called (with the dropdownlist as the sender argument) when changing the dropdown list?
For anyone who may encounter the same problem, the fix is to avoid static binding of the grid view to entity data source. Instead, bind the grid dynamically in the page load event.