basquang™ on clouds

May 18, 2009

Cascading Drop-Down List trong InfoPath Browser form

Filed under: InfoPath — basquang @ 2:43 AM

Chúng ta biết rằng việc sử lý giao diện theo kiểu master/detail hay cascading là rất hay gặp. Lấy ví dụ cho một cascading phổ biến là Address (địa chỉ). Tôi có 3 drop-down list bao gồm: Tỉnh thành phố (province), quân huyên (district) và phường xã (ward). Khi tôi select tỉnh thành phố, thì drop-down list quận huyện sẽ tự động fill theo tỉnh thành phố đó. Tương tự khi tôi select quận huyện, thì drop-down list phường xã cũng fill theo quận huyện đó.

image

Bài toán này, nếu sử dụng InfoPath không hỗ trợ browser form thì sẽ rất là đơn giản. Chúng tả chỉ cần sử dụng tính năng Filter của InfoPath control là đủ. Tuy nhiên, đối với InfoPath Browser support, các bạn biết rằng không sử được tính năng filter trên, dó đó buộc chúng ta phải can thiệp vào InfoPath Object Model. Trên web cũng có một số bài viết về việc xử lý Cascading Drop-Down List trong InfoPath sử dụng Web Service. Tuy nhiên, điều này hơi bất cấp trong việc deploy webservice và lưu trữ giữ liệu trên SQL để cho Web Service query.

Hôm nay tôi giới thiệu cho các bạn một cách xử lý Cascading  Drop-Down List nhiều cấp cho InfoPath browser form support bằng cách sử dụng InfoPath Object Model và XPath query.

Trước hết chúng ta thiết kế một XML file để lưu trữ dữ liệu cho các drop-down như sau:

<?xml version="1.0" encoding="utf-8" ?>
<DiaChi>
  <TinhTP>
    <tenTinhTP>Hanoi</tenTinhTP>
    <QuanHuyen>
      <tenQuanHuyen>Cau Giay</tenQuanHuyen>
      <PhuongXa>
        <tenPhuongXa>Dich Vong</tenPhuongXa>
      </PhuongXa>
      <PhuongXa>
        <tenPhuongXa>Mai Dich</tenPhuongXa>
      </PhuongXa>
    </QuanHuyen>
    <QuanHuyen>
      <tenQuanHuyen>Dong Da</tenQuanHuyen>
      <PhuongXa>
        <tenPhuongXa>Dong Tam</tenPhuongXa>
      </PhuongXa>
    </QuanHuyen>
  </TinhTP>
  <TinhTP>
    <tenTinhTP>Hai Phong</tenTinhTP>
    <QuanHuyen>
      <tenQuanHuyen>Le Chan</tenQuanHuyen>
      <PhuongXa>
        <tenPhuongXa>Cu Lai</tenPhuongXa>
      </PhuongXa>
    </QuanHuyen>
    <QuanHuyen>
      <tenQuanHuyen>Gia Dinh</tenQuanHuyen>
      <PhuongXa>
        <tenPhuongXa>Cam Thuong</tenPhuongXa>
      </PhuongXa>
      <PhuongXa>
        <tenPhuongXa>Dong Quang</tenPhuongXa>
      </PhuongXa>
    </QuanHuyen>
  </TinhTP>
</DiaChi>

Sau đó chúng ta add file xml này vào Data Connections của InfoPath

Tiếp theo chúng ta xử lý các Event:ChangedEventHandler đối với 3 drop-down list

Trước hết chúng ta đăng ký các Event

public void InternalStartup()
       {
           EventManager.FormEvents.Loading += new LoadingEventHandler(FormEvents_Loading);
           EventManager.XmlEvents["/my:myFields/my:tinhTP"].Changed += new XmlChangedEventHandler(tinhTP_Changed);
           EventManager.XmlEvents["/my:myFields/my:quanHuyen"].Changed += new XmlChangedEventHandler(quanHuyen_Changed);
       }

 

Trong khi load form chúng ta binding và Tỉnh thành phố drop-Down

public void FormEvents_Loading(object sender, LoadingEventArgs e)
        {           
            AddTinhTPs();
        }

        private void AddTinhTPs()
        {          
            try
            {

                XPathNavigator navAddress = DataSources["Address"].CreateNavigator();

                // Compile a standard XPath expression
                XPathExpression exprTinhTP;
                exprTinhTP = navAddress.Compile("/DiaChi/TinhTP/tenTinhTP");
                XPathNodeIterator iteratorTinhTP = navAddress.Select(exprTinhTP);
                if (iteratorTinhTP != null && iteratorTinhTP.Count >= 1)
                {
                    XPathNavigator nav = this.CreateNavigator().SelectSingleNode("/my:myFields/my:TinhTPs", this.NamespaceManager);
                    while (iteratorTinhTP.MoveNext())
                    {
                        XPathNavigator newNode = null;
                        newNode = nav.Clone();
                        newNode.SelectSingleNode("/my:myFields/my:TinhTPs/my:tinhTPDisplayName", this.NamespaceManager).SetValue(iteratorTinhTP.Current.Value);
                        newNode.SelectSingleNode("/my:myFields/my:TinhTPs/my:tinhTPValue", this.NamespaceManager).SetValue(iteratorTinhTP.Current.Value);
                        nav.InsertAfter(newNode);
                        newNode = null;
                    }
                    nav.DeleteSelf();
                    nav = null;
                }
            }
            catch (Exception ex)
            {
                WriteLog(ex.ToString());
            }
        }

 

Xử lý Event khi select item trong Tỉnh thành phố. Lúc này chúng ta mới binding đối với Quận huyện Drop-Down list

public void tinhTP_Changed(object sender, XmlEventArgs e)
        {           
            string selectedTinhTP = this.CreateNavigator().SelectSingleNode("/my:myFields/my:tinhTP", this.NamespaceManager).Value;
            if (!string.IsNullOrEmpty(selectedTinhTP))
            {
                WriteLog("tinhTP_Changed:" + selectedTinhTP + "/" + e.NewValue);
                AddQuanHuyens(selectedTinhTP);
            }
        }

private void AddQuanHuyens(string selectedTinhTP)
        {
           try
           {
               XPathNavigator navAddress = DataSources["Address"].CreateNavigator();
               // Compile a standard XPath expression
                XPathExpression exprQuanHuyen;
                string exprXPath = "/DiaChi/TinhTP[tenTinhTP=’" + selectedTinhTP + "’]/QuanHuyen/tenQuanHuyen";
                exprQuanHuyen = navAddress.Compile(exprXPath);
                XPathNodeIterator iteratorQuanHuyen = navAddress.Select(exprQuanHuyen);

                if (iteratorQuanHuyen != null && iteratorQuanHuyen.Count >= 1)
                {
                    ClearGroupNode("QuanHuyens");
                    XPathNavigator nav = this.CreateNavigator().SelectSingleNode("/my:myFields/my:QuanHuyens", this.NamespaceManager);
                    while (iteratorQuanHuyen.MoveNext())
                    {
                        XPathNavigator newNode = null;
                        newNode = nav.Clone();
                        newNode.SelectSingleNode("/my:myFields/my:QuanHuyens/my:quanHuyenDisplayName", this.NamespaceManager).SetValue(iteratorQuanHuyen.Current.Value);
                        newNode.SelectSingleNode("/my:myFields/my:QuanHuyens/my:quanHuyenValue", this.NamespaceManager).SetValue(iteratorQuanHuyen.Current.Value);
                        nav.InsertAfter(newNode);
                        newNode = null;
                    }

                    nav.DeleteSelf();
                    nav = null;
                }
                WriteLog("AddQuanHuyens:" + exprXPath);
            }
            catch (Exception ex)
            {
                WriteLog(ex.ToString());
            }
        }

 

Tương tự, chúng ta xử lý cho Phường xã.

Toàn bộ source code cho Cascading Address này được đính kèm trong bài viết này, các bạn tham khảo và cho ý kiến.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: