views:

1058

answers:

6

**UPDATED**

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 axcept i need to implement a 'ValidatorCallout' extender from the AJAX Control Toolkit. However this doesnt 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, and that you can help.

Thanks!

A: 

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.

Adrian Grigore
A: 

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.

johnofcross
Thats what im trying to do - call a client side script. Hence the conversion mentioned in my post.
Munklefish
+1  A: 

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.

svinto
+1  A: 

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

Russ Cam
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?
Munklefish
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.
Munklefish
Im not sure that the 'args.IsValid' bit has been converted properly? It doesnt appear to be treturning true or false, but rather the value of counter????????????
Munklefish
Script# might be a bit overkill for this and I believe is more intended to be used from the outset of a project to generate the client-side JavaScript for your project. If you can provide the code for AddRowstoIDList() method, then I'm sure we'll be able to provide you with a solution.
Russ Cam
Russ Cam
Ok thanks. Ive updated my question with full code and explanation. Hope it clarifies things. Ive tried the solution above by Russ Camn but its not working.
Munklefish
Will this be able to access all checkboxes, including those on the other pages / paged data?
Munklefish
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.
Russ Cam
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 http://stackoverflow.com/questions/1152946/how-to-have-a-javascript-callback-executed-after-an-update-panel-postback/1153002#1153002 for more about pageLoad
Russ Cam
A: 

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."

Dan Diplo
A: 

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/

Thomas Danecker