Select from dropdown then treeview - not holding position - c#

I am having problems with postbacks.
I have a dropdownlist that i add items to at runtime.
When i select a item in the dropbox a treeview is filled with items that have the same pID value as the object selected in the dropdownlist.
But when i select a node in the treeview everything goes back to "normal" state. The dropbox will go to selectindex -1 and the treeview disappear.
I have theese controllers in a master page if that matters.
This is my code.
public partial class Nemanet : System.Web.UI.MasterPage
{
nemanetDataContext dc = new nemanetDataContext();
Guid userGuid = (Guid)Membership.GetUser().ProviderUserKey;
bool reloadPeriod = true;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (reloadPeriod == true)
{
reloadPeriod = false;
var query = from n in dc.Nemanet_Navigations
where n.UserId == userGuid && n.Nav_pID == null
orderby n.Nav_Name ascending
select n;
foreach (var period in query)
{
ListItem period_listitem = new ListItem(period.Nav_Name, period.Nav_ID.ToString());
dropdown_navigation.Items.Add(period_listitem);
}
}
}
}
protected void dropdown_navigation_SelectedIndexChanged(object sender, EventArgs e)
{
treeview_Navigation.Nodes.Clear();
var query = from n in dc.Nemanet_Navigations
where n.UserId == userGuid
orderby n.Nav_Name ascending
select n;
foreach (var course in query)
{
if (course.Nav_pID.ToString() == dropdown_navigation.SelectedValue)
{
TreeNode course_node = new TreeNode(course.Nav_Name, course.Nav_ID.ToString());
course_node.NavigateUrl = "Default.aspx?navigateID=" + course.Nav_ID;
treeview_Navigation.Nodes.Add(course_node);
foreach (var chapter in query)
{
if (chapter.Nav_pID.ToString() == course_node.Value)
{
TreeNode chapter_node = new TreeNode(chapter.Nav_Name, chapter.Nav_ID.ToString());
chapter_node.NavigateUrl = "Default.aspx?navigateID=" + chapter.Nav_ID;
course_node.ChildNodes.Add(chapter_node);
foreach (var subject in query)
{
if (subject.Nav_pID.ToString() == chapter_node.Value)
{
TreeNode subject_node = new TreeNode(subject.Nav_Name, subject.Nav_ID.ToString());
subject_node.NavigateUrl = "editor.aspx?navigateID=" + subject.Nav_ID;
chapter_node.ChildNodes.Add(subject_node);
}
}
}
}
}
}
}
}

Any dynamically added elements will be gone after any postback, so you have add all of them again after every postback (your page is rebuild from the ground using the frontpage and page load).
To avoid reloading all the data from the database, store it in the Session.
Session["items"] = query;
if(IsPostBack) foreach(var period in (Collection)Session["items"]) dropdown_navigation.Items.Add(new ListItem(period.Nav_Name, period.Nav_ID.ToString()));

Related

I am unable to find my controls within my edittemplate in my radgrid after using insert

Currently I am working on creating a grid and I need to insert data into my radgrid. In the code behind I have set that columns are loaded in based on how many roles there are in the OnNeedDataSource event. I set the property of EditItemTemplate with a custom class Implementing the IBindableTemplate. The UniqueName of the columns is based on the id of the role. I have implemented a OnItemDataBound event where i set the current value that is stored in de DB. But when trying the InsertCommand my controls are suddenly empty. and I am not able to access them.
InsertCommand
protected void gridReviewColumns_InsertCommand(object sender, GridCommandEventArgs e)
{
GridEditableItem editableItem = ((GridEditableItem)e.Item);
var values = new Hashtable();
foreach (var gridColumn in gridReviewColumns.Columns)
{
if(gridColumn is GridTemplateColumn)
{
string uniqueName = (gridColumn as GridTemplateColumn).UniqueName;
//These controls are empty
if (editableItem[uniqueName].Controls[0] is RadioButtonList radioButtonList)
{
var value = radioButtonList.SelectedIndex;
values.Add(uniqueName, value);
}
}
}
}
OnDataBound
protected void gridReviewColumns_ItemDataBound(object sender, GridItemEventArgs e)
{
if (e.Item is GridDataItem)
{
var item = e.Item as GridDataItem;
var column = e.Item.DataItem as ComponentTypeGridReviewColumn;
if (column != null)
{
var columnRoles = column.ComponentTypeGridReviewColumnRole.ToList();
foreach (var gridColumn in gridReviewColumns.Columns)
{
if (gridColumn is GridTemplateColumn && e.Item is GridEditableItem && item.IsInEditMode)
{
var editItem = e.Item as GridEditableItem;
string uniqueName = (gridColumn as GridTemplateColumn).UniqueName;
var role = columnRoles.FirstOrDefault(cr => cr.RoleId == int.Parse(uniqueName));
if (editItem[uniqueName].Controls[0] is RadioButtonList radioButtonList)
radioButtonList.SelectedIndex = role != null ? role.UpdateAllowed ? role.MainResearcherOnly ? 3 : 2 : 1 : 0;
}
else if (gridColumn is GridTemplateColumn && e.Item is GridDataItem && !item.IsInEditMode)
{
string uniqueName = (gridColumn as GridTemplateColumn).UniqueName;
var role = columnRoles.FirstOrDefault(cr => cr.RoleId == int.Parse(uniqueName));
var itemColumn = item[uniqueName];
if (item[uniqueName].Controls[0] is Literal lit && role != null)
lit.Text = role != null ? role.UpdateAllowed ? role.MainResearcherOnly ? "Bewerken (alleen hoofdonderzoeker)" : "Bewerken" : "Lezen" : "Geen rechten";
}
}
}
}
}
OnNeedDataSource
foreach (var role in roles)
{
var gridTemplateColumn = new GridTemplateColumn
{
ColumnEditorID = role.ID.ToString(),
UniqueName = role.ID.ToString(),
HeaderText = role.RoleDescription,
EditItemTemplate = new RadioButtonColumn(role.ID == Role.StudyManagement.Researcher, role.ID.ToString()),
ItemTemplate = new LiteralColumn()
};
gridTemplateColumn.HeaderStyle.Width = Unit.Pixel(140);
gridReviewColumns.Columns.Add(gridTemplateColumn);
}
RadioButtonColumn
public class RadioButtonColumn : IBindableTemplate
{
private bool _showMainResearcherOnly;
private string uniqueName;
public RadioButtonColumn(bool showMainResearcherOnly, string uniqueName)
{
_showMainResearcherOnly = showMainResearcherOnly;
this.uniqueName = uniqueName;
}
public IOrderedDictionary ExtractValues(Control container)
{
OrderedDictionary od = new OrderedDictionary();
if (((GridEditableItem)container)[uniqueName].Controls.Count != 0)
{
od.Add(uniqueName, (RadioButtonList)((GridEditableItem)container)[uniqueName].Controls[0]);
}
return od;
}
public void InstantiateIn(Control container)
{
var radioButtonList = new RadioButtonList
{
RepeatDirection = RepeatDirection.Vertical,
RepeatLayout = RepeatLayout.Flow,
ID = uniqueName
};
radioButtonList.Items.Add(new ListItem("Geen rechten", "NoRights"));
radioButtonList.Items.Add(new ListItem("Lezen", "Read"));
radioButtonList.Items.Add(new ListItem("Bewerken", "Update"));
if (_showMainResearcherOnly)
radioButtonList.Items.Add(new ListItem("Bewerken (alleen hoofdonderzoeker)", "UpdateMainResearcher"));
container.Controls.Add(radioButtonList);
}
}
Help would be very much appriciated, if there any more info needed, just let me know

checkboxes list status with linq

Consider this scenario where you want to retrieve a List or IEnumerable of the values of all the unchecked checkboxes in checkboxlist. this code gives me the value of all checked (now) or (previously). how can I get the values of unchecked (now) and (previously) with linq. thank you
private IEnumerable <string > selectedValues
{
get
{
if (ViewState ["selectedValues"] == null && chapp . SelectedIndex >=-1 )
{
ViewState ["selectedValues"]= chapp .Items.Cast <ListItem >()
.Where (li=>li.Selected )
.Select (li=>li.Value )
.ToList ();
}else
ViewState ["selectedValues"]= Enumerable .Empty <string >();
return (IEnumerable <string >)ViewState ["selectedValues"];
}
set {ViewState ["selectedValues"] = value ;}
}
protected void chapp_SelectedIndexChanged(Object sender, EventArgs e)
{
CheckBoxList c = (CheckBoxList)sender;
var oldselection = this.selectedValues;
var newSelection = c.Items.Cast<ListItem>()
.Where(li => li.Selected )
.Select(li => li.Value);
var unchangedItems = newSelection.Except(oldselection );
}
Based on you comment:
Let's say that you have aspx page which load all the applications you have (from active directory, DB or whatever), after that assigning all the applications which the current user have (also getting those applications from what ever) ... so in your Page_Load you will have something like below:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//Load all applications
var apps = loadAllApplications();
//Load user applications
var myApps = loadUserApplications();
//Bind to checkboxlist, assuming my checkboxlist ID "chksApps"
chksApps.DataSource = apps.Select(x => new ListItem
{
Value = x.Id.ToString(),
Text = x.Name,
Selected = myApps.Any(a => x.Id == a)
});
chksApps.DataBind();
}
}
//lets say I have a Application class like that
public class Application
{
public int Id { get; set; }
public string Name { get; set; }
}
private List<int> loadUserApplications()
{
// if user already have "Paint", "Chrome" assigned
var myApps = new List<int>() { 2, 4 };
return myApps;
}
private List<Application> loadAllApplications()
{
//for testing I will create a dummy list of applications
var applications = new List<Application>() {
new Application { Id = 1, Name = "Visual Studio" },
new Application { Id = 2, Name = "Paint" },
new Application { Id = 3, Name = "Notepad" },
new Application { Id = 4, Name = "Chrome" }
};
return applications;
}
so till now the user will be able to check, uncheck what ever he want. so your checkboxlist AutoPostBack = False
so when he finish editing, assuming he will submit that to the server so he will have a submit button (lets say it's ID is "btnSave"
protected void btnSave_Click(object sender, EventArgs e)
{
//Load user applications
var myApps = loadUserApplications();
//get selected Application
var selectedApps = chksApps.Items.Cast<ListItem>()
.Where(x => x.Selected)
.Select(x => int.Parse(x.Value)).ToList();
// send request to owner to add those below apps for user "newSelectedApps"
var newSelectedApps = selectedApps.Except(myApps).ToList();
// send request to owner to remove those below apps "newUnSelectedApps"
var newUnSelectedApps = myApps.Except(selectedApps).ToList();
// those below are the unchanged apps "unChangedApps"
var unChangedApps = myApps.Intersect(selectedApps).ToList();
}
this is better than using ViewState for performance

FileUpload in DataLIst

I have datalist. Each item consists of FileUpload control.
How can I check the uploaded file after each upload?
Because I didn't know that, I tried to do something else - the check will be implemented after button click.
Note: this datalist is child of other datalist. This is nested datalist. The datasource of the parent is arraylist of orders, and the child's datasource is the products list in each order.
private void UploadProduct(DataListItem dli, ArrayList pl) // pl = productsList
{
int i = 0;
DataList DataList2 = (DataList)dli.FindControl("DataList2");
foreach (DataListItem item in DataList2.Items)
{
Product p = pl[i] as Product;
FileUpload FileUpload1 = (FileUpload)item.FindControl("FileUpload1");
if (FileUpload1.PostedFile.FileName != "" && FileUpload1.PostedFile.ContentType.Contains("jpg") && FileUpload1.PostedFile.ContentLength <= 2097151)
{
p.UploadedProduct = FileUpload1.FileBytes; // pc.UploadedProduct is byte[]
}
i++;
}
}
In the Item_Command:
if (e.CommandName == "finishOrder")
{
ArrayList ordersList = (ArrayList)Session["OrdersList"]; // the datasource of the outer datalist
int orderID = Convert.ToInt32(e.CommandArgument);
ProductsCart pc = null;
foreach (ProductsCart productsCart in ordersList) // to get the object which the button refers to
{
if (productsCart.OrderID == orderID)
pc = productsCart;
}
DataListItem item = ((DataListItem)((Button)e.CommandSource).NamingContainer); // to get the datalist item of the clicked button
FileUpload FileUpload1 = (FileUpload)(item.FindControl("FileUpload1"));
// Label errorMsg = (Label)(item.FindControl("errorMsg"));
bool flag = true;
// string imagePath;
UploadProduct(item, pc.ProductsList);
foreach (Product p in pc.ProductsList) // the check if the uploads were uploaded according to my conditions
{
if (p.UploadedProduct==null)
{
flag = false;
}
}
if (flag)
{
// do something
}
else // error
{
Page.ClientScript.RegisterStartupScript(this.GetType(), "alert", "alert('error');", true);
}
FillDataListOuter(DataList1); // datasource and databind
}
This is not working, thats why I ask for help. When I try to upload docx file it tries to execute the code if flag is true. So I guess this is not a good way to do it.
I need help, because I tried to read a lot and I couldn't find the answer.

C# entity framework storing values returns null exception

Here is my code :
protected void btnShow_Click(object sender, EventArgs e)
{
foreach (Control control in Panel1.Controls)
{
var textBox = control as TextBox;
if (textBox != null)
{
if (string.IsNullOrEmpty(textBox.Text))
{
textBox.Style["visibility"] = "hidden";
}
// textBox.Enabled = false;
var id = from t in textBox.Text
where t != null
select textBox.ID;
var text = from t in textBox.Text
where t != null
select t;
foreach (var x in id)
{
Model.crossword insert = new Model.crossword();
insert.TextBoxID = x;
daoCrossword.Insert(insert);
}
foreach (var a in text)
{
Model.crossword insert = new Model.crossword();
insert.TextBoxValue = a.ToString();
daoCrossword.Insert(insert);
}
daoCrossword.Save();
}
}
}
daoCrossword is a class file which have CRUD codes in it , i am using EF to do this , i am new to this , it gives me an error : System.NullReferenceException: Object reference not set to an instance of an object.
CRUD class file (partial) :
public void Insert(Model.crossword exe)
{
context.crosswords.AddObject(exe);
}
public void Save()
{
context.SaveChanges();
}
I have no idea what you think you're doing with these two statements, but it's probably not what you think it is.
var id = from t in textBox.Text
where t != null
select textBox.ID;
var text = from t in textBox.Text
where t != null
select t;
Then your foreach statements really make no sense because you will only ever have one item in the collections. It seems like you're trying to only save the data if there is something in the textbox, for which you should probably just do a simple if statement.
Next, you create new crossword objects in each foreach, but you only assign an id in one, and text in the other.. this is also probably not what you want. More than likely, you just want to do this:
if (!string.IsNullOrEmpty(textbox.Text))
{
Model.crossword insert = new Model.crossword();
insert.TextBoxID = textbox.ID;
insert.TextBoxValue = textbox.Text;
daoCrossword.Insert(insert);
}

Dynamic Data Custom Field Template updating a list

I have a website using dynamic data and linq to sql. This website runs 3 'subsites' and has a list of categories with a many to many relationship.
I have 3 tables and hence 3 objects in my dbml; Website, Categories, and CategoriesToWebsites
What I am trying to do is create a field template such that on my Categories/Edit.aspx page I can edit a category and specify which website the category belongs in.
The field template is CategoriesToWebsites_Edit.ascx, which is basically a checkbox list bound to the list of websites.
Code below:
public partial class CategoriesToWebsitesEdit : FieldTemplateUserControl
{
protected override void OnLoad(EventArgs e)
{
var dataSource = (LinqDataSource)this.FindDataSourceControl();
dataSource.Inserting += OnInserting;
dataSource.Updating += OnUpdating;
}
private void OnUpdating(object sender, LinqDataSourceUpdateEventArgs e)
{
var newCategory = (Category)e.NewObject;
var oldCategory = (Category)e.OriginalObject;
foreach(var listItem in WebsiteList.Items.Cast<ListItem>())
{
//check if website category already exists
var categoryToWebsite = oldCategory.CategoriesToWebsites.FirstOrDefault(x => x.WebsiteId == Convert.ToInt32(listItem.Value));
//website category exists
if (categoryToWebsite != null)
{
// check if selected for removal, remove
if (!listItem.Selected)
{
newCategory.CategoriesToWebsites.Remove(categoryToWebsite);
}
}
//we want to insert
if (listItem.Selected)
{
//website category does not exist, add
if (categoryToWebsite == null)
{
//add selected website if not already exists
newCategory.CategoriesToWebsites.Add(new CategoriesToWebsite
{
WebsiteId = Convert.ToInt32(listItem.Value)
});
}
}
}
}
private void OnInserting(object sender, LinqDataSourceInsertEventArgs e)
{
var category = (Category)e.NewObject;
foreach(var listItem in WebsiteList.Items.Cast<ListItem>())
{
if(!listItem.Selected)
continue;
category.CategoriesToWebsites.Add(new CategoriesToWebsite
{
WebsiteId = Convert.ToInt32(listItem.Value)
});
}
}
protected override void OnDataBinding(EventArgs e)
{
var websiteRepository = new WebsiteRepository();
var websites = websiteRepository.GetAll();
var websiteCategories = (IEnumerable<CategoriesToWebsite>)FieldValue;
foreach(var website in websites)
{
var currentWebsite = website;
var listItem = new ListItem(website.Name, website.Id.ToString())
{
Selected = websiteCategories == null ? false : websiteCategories.Any(w => w.WebsiteId == currentWebsite.Id)
};
WebsiteList.Items.Add(listItem);
}
}
}
When I go to Categories/Insert.aspx to create a new category, it runs through the OnInserting code fine and saves it to db just fine, everything seems to be working here.
On Categories/Edit.aspx it goes through the code just as I expect, but does not seem to save anything.
What am I missing? - I'm not too familiar with Dynamic Data Field Templates so any guidance will be much appreciated
Apparently I was going about this slightly wrong. I was simply updating the object in the linq data source, which wasn't being saved. So instead I go straight to the repository:
private void OnUpdating(object sender, LinqDataSourceUpdateEventArgs e)
{
var newCategory = (Category)e.NewObject;
var oldCategory = (Category)e.OriginalObject;
var repository = new Repository<CategoriesToWebsite>();
var ctw = repository.GetAll().Where(x => x.CategoryId == newCategory.Id);
foreach (var listItem in WebsiteList.Items.Cast<ListItem>())
{
var current = ctw.FirstOrDefault(x => x.WebsiteId == Convert.ToInt32(listItem.Value));
//current categoriesToWebsite exists
if (current != null)
{
//if not selected, remove
if (!listItem.Selected)
repository.Delete(current);
}
//does not exist
else
{
//if selected, add
if (listItem.Selected)
repository.Save(new CategoriesToWebsite()
{
CategoryId = newCategory.Id,
WebsiteId = Convert.ToInt32(listItem.Value)
}
);
}
}
UnitOfWork.Current.SubmitChanges();
}
I'm not sure if this is the proper way to do this since the field template here is doing some updating directly to the db. But it works.

Categories