1

I have an Asp.Net page with a list of options accompanied by a checkbox in a ListView control. I have applied Paging using the paging control. However I want to maintain the status of the checkboxes across the various paged pages of the ListView. I have done this with the following code

private List<int> IDs
    {
        get
        {
            if (this.ViewState["IDs"] == null)
            {
                this.ViewState["IDs"] = new List<int>();
            }
            return (List<int>)this.ViewState["IDs"];
        }
    }

protected void AddRowstoIDList()
{
    int checkAction = 0;

    foreach (ListViewDataItem lvi in lvCharOrgs.Items)
    {
        CheckBox chkSelect = (CheckBox)lvi.FindControl("chkSelect");
        if ((((chkSelect) != null)))
        {
            int ID = Convert.ToInt32(lvCharOrgs.DataKeys[lvi.DisplayIndex].Value);


            if ((chkSelect.Checked && !this.IDs.Contains(ID)))
            {
                this.IDs.Add(ID);
                checkAction += 1;
            }
            else if ((!chkSelect.Checked && this.IDs.Contains(ID)))
            {
                this.IDs.Remove(ID);
            }
        }
    }
}

protected void lvCharOrgs_ItemDataBound(object sender, ListViewItemEventArgs e)
{
    ListViewDataItem lvi = (ListViewDataItem)e.Item;
    if ((lvi.ItemType == ListViewItemType.DataItem))
    {
        // Find the checkbox in the current row
        CheckBox chkSelect = (CheckBox)lvi.FindControl("chkSelect");
        // Make sure we're referencing the correct control
        if ((chkSelect) != null)
        {
            // If the ID exists in our list then check the checkbox
            int ID = Convert.ToInt32(lvCharOrgs.DataKeys[lvi.DisplayIndex].Value);
            chkSelect.Checked = this.IDs.Contains(ID);
        }
    }

    if (Profile.proUserType == "basic")
    {//basic account so no choice of charity
        ((CheckBox)e.Item.FindControl("chkSelect")).Checked = true;
        ((CheckBox)e.Item.FindControl("chkSelect")).Enabled = false;
    }
}

Now I have a CustomValidator control which checks to ensure between 3 & 5 records have been selected. If this is true the page is valid and processed. If it is not the case (eg less than 3 or more than 5) the page is Invalid and the CustomValidator throws up a label to notify of this fact.

I use the following code on the serverside to implement this.

protected void lvCharOrgsValidator_ServerValidate(object source, ServerValidateEventArgs args)
{// Custom validate lvCharOrgs
   //update selected rows
    AddRowstoIDList();
    //get count and verify is correct range
    int counter = this.IDs.Count;
    args.IsValid = (counter >=3 && counter <=5) ? true : false;
}

This all works fine except I need to implement a 'ValidatorCallout' extender from the AJAX Control Toolkit. However this doesn't work with CustomValidators unless they implement clientSide validation. Thus I need to convert the 'lvCharOrgsValidator_ServerValidate' method to a clientside JavaScript function.

Hope this clarifies my requirements.

1
  • I have one small, off-topic point: The use of the ternary expression in the last line is redundant and unnecessary. The result of evaluating a boolean expression is a boolean value, so you can directly assign the result of the expression in parentheses to args.IsValid. Check out the code in Russ Cam's answer. Commented Aug 6, 2009 at 12:57

7 Answers 7

2

What does the following do?

AddRowstoIDList();

Something like the following is a start, but will need more details on the above method to provide a working answer

function validateRowCount(sender, args) {
    //update selected rows
    AddRowstoIDList(); // Does this add row indexes to an array?

    //get count and verify is correct range
    var counter = IDList.length;
    args.IsValid = (counter >=3 && counter <=5);
}

It might be worth looking at Script# for a longer term solution, if you're planning on doing a lot of conversion.

EDIT:

now I can see the AddRowstoIDList() method, to do this on the client-side will be slightly different. Firstly, get a reference to the DOM element that is rendered for lvCharOrgs. Probably the most straightforward way to do this in vanilla JavaScript would be to put the JavaScript function in the page and use the server tags to get the rendered ClientID.

function validateRowCount(sender, args) {
    var lvCharOrgs = document.getElementById('<%= lvCharOrgs.ClientID %>');

    var checkboxes = lvCharOrgs.getElementsByTagName('input');
    var len = checkboxes.length;
    var counter = 0;

    for(var i =0; i < len; i++) {
        if (checkboxes[i].type == "checkbox" && checkboxes[i].checked) counter++;
    }
    args.IsValid = (counter >=3 && counter <=5);
}

Should work something like this - Working Demo

add /edit to the URL if you want to see the code

Sign up to request clarification or add additional context in comments.

9 Comments

I came across Script# when doing a search for a solution. It just looked a little scary and it wasnt evident, if this was suitable. Ill definately look into it if you think its appropriate?
AddRowstoIDList(); Is just a method that does some background stuff to populate IDList.length; SO i only need to call it beforehand just to make sure IDList is upto date.
the statement (counter >=3 && counter <=5) will evaluate to true or false
No, because of the stateless nature of HTTP. Everytime a checkbox is checked/unchecked, you could increment/decrement a value in a HiddenField. When paging occurs and the page postbacks and reloads, this HiddenField value will be populated with the value it had on postback. Then just read this value in the client validation function.
Depending on how you code your JavaScript, you could either add an onclick attribute to the Checkbox control server-side which will render in the HTML, or you could write it unobtrusively using code similar to above and put inside a pageLoad function. See stackoverflow.com/questions/1152946/… for more about pageLoad
|
1

If you change int to var, your code is valid JavaScript. (But since it depends on other functions and objects you need to convert those as well.) Also if you're using the c# 3.5 compiler it will stay valid C# even with var instead of int.

Comments

1

Probably not what you want, but there is jsc:

"Web 2.0 hype? Want build better web sites, but javascript is too hard? No real IDE? Maybe you should try jsc. The web app can be built within Visual Studio 2008 or any other c# compliant IDE, and then the application magically appears. You should think of it as a smart client. Precompile your c# to javascript with jsc! As an option instead of using IIS and asp.net, you could get away by using apache, with mysql and php."

Comments

1

Have a look at this article. It applies to asp.net mvc, but it also covers some basics and you might be able to do something similar for asp.net. In particular, you might find the jquery remote validation attributes shown in the article useful for what you intend to do.

Comments

1

SharpKit converts C# to client side javascript.

https://sharpkit.github.io/

Comments

0

Well, you can always include your own javascript with custom validators. Here is a link to an article that introduces adding javascript to a validator. You just have to write your own javascript, really.

1 Comment

Thats what im trying to do - call a client side script. Hence the conversion mentioned in my post.
0

I heard about a cross-compiler from c# (or was it IL?) to JavaScript but unfortunatly do not remember the name anymore, but a google-search turned up stuff like this: http://jsc.sourceforge.net/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.