checkboxes list status with linq - c#

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

Related

Populate Drop Down List based on multiple user roles

I am trying to populate a DropDownList based on roles. I have a view in SQL with the value and text of each item based on the user role (Windows Auth) and can populate the DropDownList if a user was in all roles with:
using (var db=new GPSE_2.DAL.GPSE2Entities())
{
var locations = (from loc in db.LocationLOBViews
orderby loc.LocationNumber
select new { loc.DataValue, loc.DataText});
ddlShops.DataValueField = "DataValue" ;
ddlShops.DataTextField = "DataText";
ddlShops.DataSource = locations.ToList();
DataBind();
}
I would like to add items only the logged in user is a member of. Users can be in multiple groups(roles).
For instance, the logged in user is in a group called Location 01 LOB 100 and they are also in a group called Location 01 LOB 200 and also in Location o2 LOB 100. Only those options should appear in the DropDownList.
I was able to loop through the roles the user is in by the code below.
string UPN = UserPrincipal.Current.UserPrincipalName.ToString();
WindowsIdentity wi = new WindowsIdentity(UPN);
string GroupName;
foreach (IdentityReference group in wi.Groups)
{
GroupName = group.Translate(typeof(NTAccount)).ToString();
if (GroupName.Contains("Location 01 LOB 100"))
{
var item = new ListItem
{
Text = "Location 01 LOB 100",
Value = "01,100"
};
ddlShops.Items.Add(item);
}
}
Now I am trying to combine the 2 I ran into problems adding loc.DataValue and the loc.DataText to the DDL if the query returns results. This is where I an stuck, it adds the string in the quotes instead of the values.
using (var db = new GPSE_2.DAL.GPSE2Entities())
{
string UPN = UserPrincipal.Current.UserPrincipalName.ToString();
WindowsIdentity wi = new WindowsIdentity(UPN);
string GroupName;
foreach (IdentityReference group in wi.Groups)
{
GroupName = group.Translate(typeof(NTAccount)).ToString();
var locations = (from loc in db.LocationLOBViews
where loc.DataValue.Contains(GroupName)
orderby loc.LocationNumber
select new { loc.DataValue, loc.DataText });
if (locations !=null)
{
var item = new ListItem
{
Text = "DataText",
Value = "DataValue"
};
ddlShops.Items.Add(item);
}
}
}
Thanks,
-Doug
I got it working by creating a list of groups the user is in and then populating the Drop Down List with the appropriate information.
private List<string> GetGroups()
{
string UPN = UserPrincipal.Current.UserPrincipalName.ToString();
List<string> result = new List<string>();
WindowsIdentity wi = new WindowsIdentity(UPN);
foreach (IdentityReference group in wi.Groups)
{
string GroupName = group.Translate(typeof(NTAccount)).ToString();
//if text location and lob is in the name add to results
if (GroupName.Contains("Location") && GroupName.Contains("LOB"))
{
string DataValue1 = GroupName.Substring(GroupName.Length - 3);
string DataValue2 = GroupName.Substring(GroupName.Length - 10, 2);
string DataValue = DataValue2 + "," + DataValue1;
result.Add(DataValue);
}
}
result.Sort();
return result;
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
using (var db = new GPSE2Entities())
{
for (int i = 0; i < GetGroups().ToArray().Length; i++)
{
string DataValue = GetGroups().ToArray()[i].ToString();
var locations = (from loc in db.LocationLOBViews
where loc.DataValue == DataValue
orderby loc.LocationNumber
select loc).FirstOrDefault();
if (locations != null)
{
var item = new ListItem
{
Text = locations.DataText,
Value = locations.DataValue
};
ddlShops.Items.Add(item);
}
}
}
ddlShops.Items.Insert(0, "--Select Location and LOB--");
}
}

Checkbox turning multiple values true

I've been stuck of this for a while and would love some insight.
When I add a new user or source and check the drawn checkbox, it causes the bool to be true when checked, as expected.
However it also checks all the other users connected to that source as true or false.
[before]
[after]
This only occurs when I load the XML file into my program that already had existing data, then add new Users or Sources via the UI.
this is a part of the LoadXML Method.
// Load the source list
sourceProps.SystemSources.Clear();
fCMUserSourceBindingSource.Clear();
fCMSourceBindingSource.Clear();
foreach (FusionSource src in fusionSystem.sourceList)
{
FCMSource fSource = new FCMSource(src);
sourceProps.SystemSources.Add(fSource);
fCMSourceBindingSource.Add(fSource);
fCMUserSourceBindingSource.Add(fSource);
}
txtSourceID.Text = sourceProps.GenerateNextSourceId();
// Load the user data from the fusionSystem object.
userProfile.SystemUserList.Clear();
//currently clears grid. might need to clear list instead
fCMUserBindingSource.Clear();
foreach (FusionUser usr in fusionSystem.userList)
{
FCMUser fUser = new FCMUser(usr);
userProfile.SystemUserList.Add(fUser);
fCMUserBindingSource.Add(fUser);
foreach (FusionSourcePermission srcPerm in usr.SourcePermissionList)
{
FCMSource fSource = new FCMSource(srcPerm);
fUser.fusionUserSources.Add(fSource);
}
}
AddColumnsUsersToSourceAllocation();
txtUserID.Text = userProfile.GenerateNextUserId();
// Load the zone group data from the fusionSystem object
zoneProps.systemZoneGroupList.Clear();
fCMZoneGroupBindingSource.Clear();
Any help would be appreciated.
Edit
The ListView is not binded and all the 'checking' is done programmatically when the user activates the click event.
private void lstSourceToUser_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
if (e.ColumnIndex > 1)
{
int usrIndex = userProfile.GetUserIndexByID(e.Header.Name);
int srcIndex = userProfile.GetUsersSourceIndex(e.Header.Name, e.Item.SubItems[0].Text);
Graphics g = e.Graphics;
CheckBoxRenderer.DrawCheckBox(g,new Point((e.Bounds.X + e.Bounds.Width/2 -10 ),(e.Bounds.Y)), userProfile.SystemUserList[usrIndex].fusionUserSources[srcIndex].UserSourceChkBox.MyCheckedState ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal);
}
else
// Draw the other subitems with default drawing.
e.DrawDefault = true;
}
Edit
This is the FCMSource constructor.
public FCMSource(string sourceId, string sourceName, string icnId, string lstIndx)
{
id = sourceId;
icon = icnId;
name = sourceName;
listIndex = lstIndx;
UserSourceCheckState = false;
UserSourceChkBox = new MyCheckBoxItem(false);
}
public FCMSource(FCMSource fSource, bool chk)
{
name = fSource.name;
icon = fSource.icon;
id = fSource.id;
listIndex = fSource.listIndex;
UserSourceCheckState = chk ? true : false;
UserSourceChkBox = new MyCheckBoxItem(chk);
}
And this is the FCMUser constructor which contains the different Sources.
public FCMUser(string userid, string nm, string icn, string pinNo, CheckBox pinEn, string lstIndx)
{
id = userid;
name = nm;
icon = icn;
pin = pinNo;
pinEnabled = pinEn.CheckState;
chkBoxPINEnable = new MyCheckBoxItem(false);
fusionUserSources = new List<FCMSource>();
ListIndex = lstIndx;
updateCheckbox();
}

Passing variable from controller to Devexpress GridView Column EndCallBack JS

I gave a Devexpress GridView which represent addresses. Two cascading combobox (Governorate- Area). When the user choose a Governorate the area combo will filtered according to the Governorate chased. When the user doesn't know the corresponding Governorate for the area, he only start by choosing the area and the governorate combobox will fill with the right governorate.
In index.chtml
<script type="text/javascript">
function governorateCombo_SelectedIndexChanged(s, e) {
areaCode.PerformCallback();
}
function AreaCombo_BeginCallback(s, e) {
e.customArgs['governorateCode'] = governorateCode.GetValue();
}
function areaCombo_SelectedIndexChanged(s, e) {
governorateCode.PerformCallback();
}
function GovernorateCombo_BeginCallback(s, e) {
e.customArgs['areaCode'] = areaCode.GetValue();
}
function GovernorateCombo_EndCallback(s, e) {
benGeoGridView.Refresh();
var bla = '#Session["governorateCode"]';
var item = s.FindItemByValue(bla);
s.SetSelectedItem(item);
}
ComboboxGovernoratePartial.chtml
#Html.DevExpress().ComboBox(settings =>
{
settings.CallbackRouteValues = new { Controller = "benFile", Action = "ComboBoxGovernoratePartial" };
settings.Name = "governorateCode";
settings.Properties.TextField = "governorateName1";
settings.Properties.ValueField = "governorateCode";
settings.Properties.ValueType = typeof(string);
settings.Width = 220;
settings.Properties.EnableSynchronization = DefaultBoolean.False;
settings.Properties.IncrementalFilteringMode = IncrementalFilteringMode.StartsWith;
if (Thread.CurrentThread.CurrentCulture.Name.Substring(0, 2) == "ar")
{
settings.RightToLeft = DefaultBoolean.True;
}
settings.Properties.ClientSideEvents.BeginCallback = "GovernorateCombo_BeginCallback";
settings.Properties.ClientSideEvents.SelectedIndexChanged = "governorateCombo_SelectedIndexChanged";
settings.Properties.ClientSideEvents.EndCallback = "GovernorateCombo_EndCallback";
}).BindList(Model).Bind(ViewData["governorateCode"]).GetHtml()
In controller:
public ActionResult ComboBoxGovernoratePartial()
{
string areaCode = (Request.Params["areaCode"] != null) ? Request.Params["areaCode"] : "-1";
List<governorateName> governorateNames = new List<governorateName>();
governorateMaster governorateMaster = new governorateMaster();
if (areaCode != null)
{
Session["governorateCode"] = Masters.areaMasters.First(a => a.areaCode == areaCode).governorateCode; ;
ViewData["governorateCode"] = Masters.areaMasters.First(a => a.areaCode == areaCode).governorateCode;
governorateNames = Masters.governorateNames.Where(a => a.langCode.ToLower() == Thread.CurrentThread.CurrentCulture.Name.Substring(0, 2)).ToList();
}
return PartialView(governorateNames.ToList());
}
When the user choose the area, (in js) I call perform call back for the governorate combobox that the controller pick up the right governorate to populate in the governorate combobox. The problem is that when I send the governorate code in a ViewData it is always null. In a Session varible, the value of it is the one at page load not the updated one in the controller.
Any suggestion ?
Sorry for your time guys
For that, you can try:
TempData["yourVar"]

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.

Select from dropdown then treeview - not holding position

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()));

Categories