Link to home
Start Free TrialLog in
Avatar of Victor  Charles
Victor CharlesFlag for United States of America

asked on

Help with MoveNext,MovePrevious,MoveFirst and MoveLast record featiures

Hello,

After I was able to successfully filter the data with the code in the related case, I tried to move to the next record with the code below but running into some problems.

I'm getting error:

'CmbRec' has a SelectedIndex which is invalid because it does not exist in the list of items.
Parameter name: value

on Line: CmbRec.SelectedIndex = Val(Subnode1.InnerText) - 1

Code:

 Dim NodeCount As Integer = LinkStream.SelectNodes("Root/Link").Count
        If (NodeNumber < NodeCount) Then
            NodeNumber += 1   'Move to some next node
            Dim node As XmlNode = LinkStream.SelectSingleNode("Root/Link[" & NodeNumber & "]")
            Dim Subnode1 As XmlNode = node.ChildNodes(0)
            Dim Subnode2 As XmlNode = node.ChildNodes(1)

            CmbRec.SelectedIndex = Val(Subnode1.InnerText) - 1
            CmbDonor.SelectedIndex = Val(Subnode2.InnerText) - 1
            btnPrev.Enabled = True
            If (NodeNumber = NodeCount) Then
                btnNext.Enabled = False
            End If
        Else
            NodeNumber = 0   ' Reset count so start searching from zero (You can change strategy)
            ' btnNext.Enabled = False
        End If

Can you please help me solve this issue.

Thanks,

Victor
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

That error would suggest that the value is invalid, and the return is 0.

     Val(Subnode1.InnerText) - 1
Avatar of Victor  Charles

ASKER

Hello,

I'm using the code below to move to the next record but for some reason, after I move to the 4th record, it doesn't work. For example, I hard coded the value 4 in my code for ReceiverID, which has 6 records in Link.xml, Therefore when I press the Next button I was expecting to Move Next all the way to record number 6, but as mentioned after record number 4, it doesn't work, after a few click it jumps back to record number3. Below are my code and xml files, can you please help me figure out why Move Next button doesn't work after the 4th record?

CodeA: (Load comboboxes where ReceiverID = 4 in link.xml)

 lnk.Load(Application.StartupPath & "/link.xml") 'My.Resources.Link)
        Dim RecName As XmlNodeList = RecStream.SelectNodes("Root/Receiver")
        Dim DonorName As XmlNodeList = DonorStream.SelectNodes("Root/Donor")

        Dim donorlst As New DataTable()
        donorlst.Columns.Add("ID")
        donorlst.Columns.Add("Name")
        Dim reclst As New DataTable
        reclst.Columns.Add("ID")
        reclst.Columns.Add("Name")
        Dim x As Integer
        x = 4
        For Each xnLink As Xml.XmlNode In lnk.SelectNodes("/Root/Link[ReceiverID='" & x & "']")

            ' For Each n As XmlNode In lnk
            Dim rID As Integer = Val(xnLink.ChildNodes(1).InnerText)
            Dim dID As Integer = Val(xnLink.ChildNodes(2).InnerText)

            For Each node As XmlNode In RecName
                If node.ChildNodes(0).InnerText = rID.ToString Then
                    ' reclst.Rows.Add(New Object() {rID, node.ChildNodes(1).InnerText})
                    reclst.Rows.Add(New Object() {rID, node.ChildNodes(0).InnerText})
                End If
            Next

            For Each node As XmlNode In DonorName
                If node.ChildNodes(0).InnerText = dID.ToString Then
                    'donorlst.Rows.Add(New Object() {node.ChildNodes(0).InnerText, node.ChildNodes(1).InnerText})
                    donorlst.Rows.Add(New Object() {dID, node.ChildNodes(1).InnerText})
                End If
            Next
        Next
        cc = donorlst.Rows.Count
        CmbDonor.DataSource = donorlst
        CmbDonor.DisplayMember = "Name"
        CmbDonor.ValueMember = "ID"

        CmbRec.DataSource = reclst
        CmbRec.DisplayMember = "Name"
        CmbRec.ValueMember = "ID"

CoeB: Move Next Button
 MsgBox(lnk.SelectNodes("Root/Link").Count)
        Dim NodeCount As Integer = lnk.SelectNodes("Root/Link").Count
        If (NodeNumber < cc) Then
            NodeNumber += 1
            Dim node As XmlNode = lnk.SelectSingleNode("Root/Link[" & NodeNumber & "]")
            Dim Subnode1 As XmlNode = node.ChildNodes(1)
            Dim Subnode2 As XmlNode = node.ChildNodes(2)
            CmbRec.SelectedIndex = Val(Subnode1.InnerText) - 1
            CmbDonor.SelectedIndex = Val(Subnode2.InnerText) - 1
        Else
            NodeNumber = 0   ' Reset count so start searching from zero (You can change strategy)
        End If

Link.xml (Last 6 records include ReceiverID = 4)

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Root>
  <Link>
    <LinkID>1</LinkID>
   <ReceiverID>1</ReceiverID>
   <DonorID>2</DonorID></Link>
  <Link>
    <LinkID>2</LinkID>
    <ReceiverID>1</ReceiverID>
    <DonorID>3</DonorID>
  </Link>
  <Link>
    <LinkID>3</LinkID>
    <ReceiverID>1</ReceiverID>
    <DonorID>4</DonorID>
  </Link>
  <Link>
    <LinkID>4</LinkID>
    <ReceiverID>2</ReceiverID>
    <DonorID>4</DonorID>
  </Link>
<Link>
 <LinkID>5</LinkID>
    <ReceiverID>1</ReceiverID>
    <DonorID>2</DonorID>
  </Link>
  <Link>
    <LinkID>6</LinkID>
    <ReceiverID>2</ReceiverID>
    <DonorID>2</DonorID>
  </Link>
  <Link>
    <LinkID>7</LinkID>
    <ReceiverID>4</ReceiverID>
    <DonorID>1</DonorID>
  </Link>
  <Link>
    <LinkID>8</LinkID>
    <ReceiverID>4</ReceiverID>
    <DonorID>2</DonorID>
  </Link>
  <Link>
    <LinkID>9</LinkID>
    <ReceiverID>4</ReceiverID>
    <DonorID>3</DonorID>
  </Link>
<Link>
    <LinkID>10</LinkID>
    <ReceiverID>4</ReceiverID>
    <DonorID>4</DonorID>
  </Link>
  <Link>
    <LinkID>11</LinkID>
    <ReceiverID>4</ReceiverID>
    <DonorID>5</DonorID>
  </Link>
  <Link>
    <LinkID>12</LinkID>
    <ReceiverID>4</ReceiverID>
    <DonorID>6</DonorID>
  </Link>
</Root>

ASKER CERTIFIED SOLUTION
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi,

Can you please send me an example using my project information, I still do not
see how this approach will help me with moving to Next or previous records.

Thanks,

Victor
Hello,

I'm trying the sample project to better understand how LinQToXML works, but I'm getting error:
Error: The name 'Data' does not exist in the current context      
On Line: Data.DAL.Save(customer);

How do I fix this error?

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;

namespace LINQXMLCSHARP
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {

        }
        public class Customer
        {
            public int ID { get; set; }
            public string Forename { get; set; }
            public string Surname { get; set; }
            public string DOB { get; set; }
            public string Location { get; set; }
        }
        public static Customer GetCustomer(int customerID)
        {
            XDocument data = XDocument.Load(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));

            return (from c in data.Descendants("Customer")
                    where c.Attribute("ID").Value.Equals(customerID.ToString())
                    select new Customer()
                    {
                        ID = Convert.ToInt32(c.Attribute("ID").Value),
                        Forename = c.Element("Forename").Value,
                        Surname = c.Element("Surname").Value,
                        DOB = c.Element("DOB").Value,
                        Location = c.Element("Location").Value

                    }).FirstOrDefault();
        }

        public static List<Customer> GetCustomers()
        {
            XDocument data = XDocument.Load(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));

            return (from c in data.Descendants("Customer")
                    orderby c.Attribute("Surname")
                    select new Customer()
                    {
                        ID = Convert.ToInt32(c.Attribute("ID").Value),
                        Forename = c.Element("Forename").Value,
                        Surname = c.Element("Surname").Value,
                        DOB = c.Element("DOB").Value,
                        Location = c.Element("Location").Value

                    }).ToList();
        }

        public static void Save(Customer customer)
        {
            XDocument data = XDocument.Load(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));

            if (customer.ID > 0)
            {
                XElement customerElement = data.Descendants("Customer").Where(c => c.Attribute("ID").Value.Equals(customer.ID.ToString())).FirstOrDefault();
                if (customerElement != null)
                {
                    customerElement.SetElementValue("Forename", customer.Forename);
                    customerElement.SetElementValue("Surname", customer.Surname);
                    customerElement.SetElementValue("DOB", customer.DOB);
                    customerElement.SetElementValue("Location", customer.Location);

                    data.Save(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));
                }
            }
            else
            {
                XElement newCustomer = new XElement("Customer",
                                                        new XElement("Forename", customer.Forename),
                                                        new XElement("Surname", customer.Surname),
                                                        new XElement("DOB", customer.DOB),
                                                        new XElement("Location", customer.Location)
                                                    );

                newCustomer.SetAttributeValue("ID", GetNextAvailableID());

                data.Element("Customers").Add(newCustomer);
                data.Save(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));
            }
        }

        private static int GetNextAvailableID()
        {
            XDocument data = XDocument.Load(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));

            return Convert.ToInt32(
                    (from c in data.Descendants("Customer")
                     orderby Convert.ToInt32(c.Attribute("ID").Value) descending
                     select c.Attribute("ID").Value).FirstOrDefault()
                    ) + 1;
        }

        public static void Delete(Customer customer)
        {
            XDocument data = XDocument.Load(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));

            XElement customerElement = data.Descendants("Customer").Where(c => c.Attribute("ID").Value.Equals(customer.ID.ToString())).FirstOrDefault();
            if (customerElement != null)
            {
                customerElement.Remove();
                data.Save(HttpContext.Current.Server.MapPath("~/Data/Customers.xml"));
            }
        }

        protected void btnAddCustomer_Click(object sender, EventArgs e)
        {
            Customer customer = new Customer()
            {
                Forename = txtForename.Text.Trim(),
                Surname = txtSurname.Text.Trim(),
                DOB = txtDOB.Text.Trim(),
                Location = txtLocation.Text.Trim()
            };

            Data.DAL.Save(customer); ******************Error Line************************

            ClearForm();
            gvCustomers.DataBind();
            txtForename.Focus();
        }

        private void ClearForm()
        {
           txtForename.Text = string.Empty;
            txtSurname.Text = string.Empty;
           txtDOB.Text = string.Empty;
           txtLocation.Text = string.Empty;
        }


    }
   

}
I removed Data.DAL.Save(customer);  from the code and ran the project and received the following error:

The type specified in the TypeName property of ObjectDataSource 'odsCustomers' could not be found.

I'm not sure if it's cause I removed that line or a totally separate issue.

How do I create the ObjectDataSource?

Thanks,

Victor
Hi,

Going back to my initial post, I figured out the reason the MoveNext button doesn't work properly is because I am looping through the original Link.xml fikle insatead of the one that was filtered. Is there a way to create a temp Link.xml just for thet session and pass it the values from the filtered search to use for the Next button. I admit it sounds complicated but would like to get tt work anyway possible and try to improve it at a later stage.

MoveNext Code:

 Dim NodeCount As Integer = lnk.SelectNodes("Root/Link").Count
        NodeNumber += 1
        Dim node As XmlNode = lnk.SelectSingleNode("Root/Link[" & NodeNumber & "]")
        Dim Subnode1 As XmlNode = node.ChildNodes(1)
        Dim Subnode2 As XmlNode = node.ChildNodes(2)
        MsgBox(Val(Subnode1.InnerText))
        MsgBox(Val(Subnode2.InnerText))
        CmbRec.SelectedIndex = Val(Subnode1.InnerText) - 1
        CmbDonor.SelectedIndex = Val(Subnode2.InnerText) - 1

As mentioned code is going using original Link.xml file instead of Lnk created when filtered data with code below:
Dim RecName As XmlNodeList = RecStream.SelectNodes("Root/Receiver")
        Dim DonorName As XmlNodeList = DonorStream.SelectNodes("Root/Donor")

        Dim donorlst As New DataTable()
        donorlst.Columns.Add("ID")
        donorlst.Columns.Add("Name")
        Dim reclst As New DataTable
        reclst.Columns.Add("ID")
        reclst.Columns.Add("Name")
        Dim x As Integer
        x = 5
        For Each xnLink As Xml.XmlNode In lnk.SelectNodes("/Root/Link[ReceiverID='" & x & "']")
                  ' For Each n As XmlNode In lnk
            Dim rID As Integer = Val(xnLink.ChildNodes(1).InnerText)
            Dim dID As Integer = Val(xnLink.ChildNodes(2).InnerText)
        '*****
       'How do I add code to put  rID and dID values in a Temp Link file for each session?
       '*******
            For Each node As XmlNode In RecName
                If node.ChildNodes(0).InnerText = rID.ToString Then
                    reclst.Rows.Add(New Object() {rID, node.ChildNodes(1).InnerText})
                End If
            Next

            For Each node As XmlNode In DonorName
                If node.ChildNodes(0).InnerText = dID.ToString Then
                    'donorlst.Rows.Add(New Object() {node.ChildNodes(0).InnerText, node.ChildNodes(1).InnerText})
                    donorlst.Rows.Add(New Object() {dID, node.ChildNodes(1).InnerText})
                End If
            Next
        Next
        cc = donorlst.Rows.Count
        CmbDonor.DataSource = donorlst
        CmbDonor.DisplayMember = "Name"
        CmbDonor.ValueMember = "ID"

        CmbRec.DataSource = reclst
        CmbRec.DisplayMember = "Name"
        CmbRec.ValueMember = "ID"

Hi,

I managed to created a LinkTemp.xml file with the values that meet my search criteria (i.e. x = 5), using the codeA below and was able to Move Next to the correct records. Now when the users select one of the records and makes a change in the Receiver combobox for example, what code would replace the old ID with the New ID of the data selected to the original Link.xml file? I started working with CodeB but couldn't figure it out, instaed of changing the values, I'm getting a new record with the selected Values IDs.

CodeA:
            Dim xml As String = lnk.InnerXml
            Dim newline As String = Environment.NewLine
            Dim replacement As String = "<Link><ReceiverID>" & rID & "</ReceiverID><DonorID>" & dID & "</DonorID></Link>"
            lnk.InnerXml = lnk.InnerXml.Replace("</Root>", "") & replacement & "</Root>"
            lnk.Save(Application.StartupPath & "/LinkTemp.xml")

CodeB:

 If (NodeNumber = 0) Then
            NodeNumber = 1
        End If
        Dim link As XmlNode = LinkStream.SelectSingleNode("Root/Link[" & NodeNumber & "]")

        Dim newnode As XmlNode = link.Clone '(True)
        newnode.InnerXml = "<ReceiverID>" & CmbRec.SelectedValue & "</ReceiverID>" & "<DonorID>" & CmbDonor.SelectedValue & "</DonorID>"

        link.InnerXml = newnode.InnerXml

        LinkStream.Save(Application.StartupPath & "/Link.xml")
You are the best one to decide what you want to do, so my "job" is to only suggest and guide.  I don't quite understand your problem space, and your question either.  A "temp" file should be just keeping a different variable reference to the information.  Is it the filtered part that is causing you difficulty?
I prefer you method but it was in C# and I couldn't get the sample to work to help me understand the code in the sample project, as mentioned I'm getting:
Error: The name 'Data' does not exist in the current context      
On Line: Data.DAL.Save(customer);
Therefore I decide  to see if I can work more on my old code to try to make it work,
Basically what I need to do is move the Next/Previous record after I obtain my results from codeA below.

CodeA: (Load comboboxes where ReceiverID = 4 in link.xml)

 lnk.Load(Application.StartupPath & "/link.xml") 'My.Resources.Link)
        Dim RecName As XmlNodeList = RecStream.SelectNodes("Root/Receiver")
        Dim DonorName As XmlNodeList = DonorStream.SelectNodes("Root/Donor")

        Dim donorlst As New DataTable()
        donorlst.Columns.Add("ID")
        donorlst.Columns.Add("Name")
        Dim reclst As New DataTable
        reclst.Columns.Add("ID")
        reclst.Columns.Add("Name")
        Dim x As Integer
        x = 4
        For Each xnLink As Xml.XmlNode In lnk.SelectNodes("/Root/Link[ReceiverID='" & x & "']")

            ' For Each n As XmlNode In lnk
            Dim rID As Integer = Val(xnLink.ChildNodes(1).InnerText)
            Dim dID As Integer = Val(xnLink.ChildNodes(2).InnerText)

            For Each node As XmlNode In RecName
                If node.ChildNodes(0).InnerText = rID.ToString Then
                    ' reclst.Rows.Add(New Object() {rID, node.ChildNodes(1).InnerText})
                    reclst.Rows.Add(New Object() {rID, node.ChildNodes(0).InnerText})
                End If
            Next

            For Each node As XmlNode In DonorName
                If node.ChildNodes(0).InnerText = dID.ToString Then
                    'donorlst.Rows.Add(New Object() {node.ChildNodes(0).InnerText, node.ChildNodes(1).InnerText})
                    donorlst.Rows.Add(New Object() {dID, node.ChildNodes(1).InnerText})
                End If
            Next
        Next
        cc = donorlst.Rows.Count
        CmbDonor.DataSource = donorlst
        CmbDonor.DisplayMember = "Name"
        CmbDonor.ValueMember = "ID"

        CmbRec.DataSource = reclst
        CmbRec.DisplayMember = "Name"
        CmbRec.ValueMember = "ID"


After achieving to Move to Next?Previous records, I need to be able to Modify the data in a particular record or delete the record. My main issue is with the code to move to Next/Previous records, if possible I would like to keep the approach in CodeA to filter the record, but I'm willing to change that approach if I can find a better one that would help me achieve all my requirements.


Victor
Hello,

The code below finds all the records that meets a search criteria and displays the data in two web controls. Is there a way to modify the For Each command to only find one record for each click of the button (for example Find next or Find Previous) . I believe this might be a solution for moving to Next or Previous records. I think the best approach would be to keep the existing code and display the data when Moving to Next or Previous records by moving through the tables, but I can't figure out how to do that also.

            For Each xnLink As Xml.XmlNode In xdLink.SelectNodes("/Root/Link[ReceiverID='" & C1Country.SelectedItem.Value & "']")

                ' Extract the ReceiverID and DonorID values from the current node
                Dim ReceiverID As String
                Dim DonorID As String

                ReceiverID = xnLink.SelectSingleNode("ReceiverID").InnerText
                DonorID = xnLink.SelectSingleNode("DonorID").InnerText

                ' Perform another similar search based upon the Donor XML file
                For Each xnDonor As Xml.XmlNode In xdDonor.SelectNodes("/Root/Donor[DonorID='" & DonorID & "']")

                    ' Extract the DonorID and Name values from the current node
                    Dim DonorID2 As String
                    Dim Name As String

                    DonorID2 = xnDonor.SelectSingleNode("DonorID").InnerText
                    Name = xnDonor.SelectSingleNode("Name").InnerText
                    dtDonor.Rows.Add({DonorID2, Name})
                Next

                ' Perform yet another practically identical search on the Receiver XML file
                For Each xnReceiver As Xml.XmlNode In xdReceiver.SelectNodes("/Root/Receiver[ReceiverID='" & ReceiverID & "']")
                    ' Extract the ReceiverID and Name values from the current node
                    Dim ReceiverID2 As String
                    Dim Name As String

                    ReceiverID2 = xnReceiver.SelectSingleNode("ReceiverID").InnerText
                    Name = xnReceiver.SelectSingleNode("Name").InnerText
                    dtReceiver.Rows.Add({ReceiverID2, Name})

                Next
            Next
        End If

Code: Displays

Receiver_Control  (However users will only see first row, code will be implement so when users click on combobo lit of all countries will be listed to give them a choice to update the data)
BEL
CAN
DEU
ESP

Donor Control

USA
BEL
GBR
CAN

I need Press Next button and see

Receiver
CAN


Donor
BEL

Press Next button and see:

Receiver
DEU


Donor
GBR

Press Next button and see:

Receiver
ESP


Donor
CAN

and when Users press Previous button they will see previois record:

Receiver
DEU


Donor
GBR
Hi again,

Is there a way to open dtReciver and dtDonor tables and move through their records created from the previous post, using the Move Next/Previous buttons while displaying the data in the comboboxes?

Thanks,

Victor
Hello again,

After binding the tables to CmbRec and CmbDonor with the syntax below, I can find a property to move to next or previous records, do you know if such properties exiist or another way to move to next or previous records?,

        CmbRec.DataSource = dtReceiver
        CmbRec.DataTextField = "Name"
        CmbRec.DataValueField = "ReceiverID"
        CmbRec.DataBind()

        CmbDonor.DataSource = dtDonor
        CmbDonor.DataTextField = "Name"
        CmbDonor.DataValueField = "DonorID"
        CmbDonor.DataBind()
Thanks!