basquang™ on clouds

March 8, 2012

SharePoint 17: Query Form Library data sử dụng LINQ to XML

Filed under: InfoPath,SharePoint — basquang @ 1:47 PM
Tags:
Video hướng dẫn cách query InfoPath data trên SharePoint Form Library sử dụng LINQ to XML
Advertisements

March 29, 2010

Cascading Drop-Down List in SharePoint 2010 using InfoPath 2010

Filed under: InfoPath,SharePoint — basquang @ 3:09 PM

Cascading drop-down is a common business requirement. SharePoint 2007 does not support cascading drop-down list by default. User have to write custom SharePoint field and it’s not easy to implement. With SharePoint 2010, User able to customize SharePoint form in easy way by using the powerful of InfoPath Designer. Following is the step guides to create a cascading drop-down list solution in SharePoint 2010 without require a lot of IT knowledge.

Scenario: We build a cascading for Address List. We have three list: City, District and Ward

1. Create City List

– In SharePoint 2010, create a custom List and named as “City”

– Add Two Item to this list: Hanoi and TP HCM

2. Create District List

– In SharePoint 2010, create a custom List and named as “District”

– Create a Lookup column named as “City”. This column get information from City List in the column Title.

– Add 4 items to District list

image

3. Create Ward List

– In SharePoint 2010, create a custom List and named as “Ward”.

– Create a Lookup column named as “City”. This column get information from City List in the column Title.

– Create a Lookup column named as “District”. This column get information from District List in the column Title.

– Create on Add new Item link you will see. When we choose City, District still have 4 item.

image

4. Customize Ward form to meet cascading requirement

– In Ward List, click on Customize Form ribbon button

image

– System will automatically open the form template of Ward list in InfoPath Designer

image

– Right click on District drop-down list control then select Drop-Down List box Properties from menu to open the properties windows

image

– In Data Source. Click on Add button

– In Data Connection Wizard, click on Next button

image

– In Select the source of your data, choose SharePoint library of list then click Next button

image

– In SharePoint Site details screen, click on Next button

image

– In Select a list of library, choose District the click on Next button

image

– In select fields: Choose Title, City, ID then click on Next button

image

– In next screen, choose Next button

image

– Leave the default name for the connection as “District1” then click Finish button

image

– Now, You will see the Data Source of Drop-Down list box is District1

image

– In Entries section, click on the tree button to select XPath

– In Select a Field or Group dialog, click on Filter Data… button

image

– In Filter Data click on Add… button

image

– In specify Filter Conditions, in the first drop-down list choose Select a field or group

image

– Select a Field or Group opened. Select District1 as Data Source, choose City in dataFields then click OK

image

– In specify Filter Conditions, in the last drop-down list choose Select a field or group

image

– Select a Field or Group opened. Select Main as Data Source then choose City in dataFields then click OK

image

– Click on OK to close specify Filter Conditions dialog

– Click on OK to close Filter Data dialog

– Click on OK to close Select a Field or Group

– In Drop Down List box properties, choose d:ID in Value: section then click OK to close this

image

– In InfoPath Designer, close the Windows then choose the Save and Publish button

image

– After Publishing complete, back to Ward list then click on Add new item link. You will see the result

image image

Two drop-down list has been cascading.

Conclusion

SharePoint 2010 provides a easy way for none IT to custom the look and feel of SharePoint by using InfoPath Designer, SharePoint Designer. Customize form in InfoPath Designer 2010 is a great new feature of SharePoint 2010. It’s cool!

August 20, 2009

InfoPath: Duplicate Attribute error

Filed under: InfoPath — basquang @ 5:03 AM

“The formula contains one or more errors.
Duplicate attribute”

I got it when trying to add ,xsl as Data Connections to InfoPath then add new Rules to controls. Following this guide. It’s resolved the problem

http://www.softobject.com/sites/Blog/Lists/Posts/Post.aspx?ID=4

DUPLICATE ATTRIBUTE ERROR:

This happens when a XSL file is added to the form as 2ndary data source.  The namespace in the XSL conflicts what’s in Form’s ns. 

RESOLUTION:

Do not add XSL as 2ndary data source.  Instead add it as form’s Resource File.  Change your code that might be doing the XSLT transform to load the XSL manually.  This fixes it as charm!

Work around code instead of havinf XSL as a secondary data source

WITH XSL AS SECONDARY DATA SOURCE, YOU COULD HAVE DONE SOMETHING LIKE THIS:

custom.HTMLDocument.body.innerHTML = thisXDocument.DOM.transformNode(thisXDocument.GetDOM("SummaryReport"));

NOW SINCE THAT CAUSES NAMESPACE CONFUSION/CONFLICT, DO THE XSLT LIKE THIS:

IXMLDOMDocument XSLTFileDOM = thisXDocument.CreateDOM(); 
XSLTFileDOM.async = false; 
XSLTFileDOM.validateOnParse = false; 
XSLTFileDOM.load("SummaryReport.xslt"); 
custom.HTMLDocument.body.innerHTML = thisXDocument.DOM.transformNode(XSLTFileDOM);

-DANIEL

It work for JScript. But C#, I don’t get the solution yet.

August 13, 2009

Export InfoPath form to Word 2003 document sử dụng XSLT, XPath và C#

Filed under: InfoPath — basquang @ 4:01 AM

Trong bài viết trước, Export InfoPath form to Word 2003 document sử dụng XSLT và XPath tôi đã đã hướng dẫn các bạn cách Export InfoPath form sử dụng JScript code. Bài này hướng dẫn các bạn một cách khác, sử dụng C# Code.

Chúng ta cũng thực hiện các bước tương tự như bài trước. Tuy nhiên lựa chọn Programming language ở đây là C#. Chúng ta sử dụng đoạn code sau cho Button Event

   1: //Retrieve the xsl to use to transform the InfoPath form into document.xml
   2: DataSource ds = this.DataSources["XMLToWordML"];
   3: XslCompiledTransform trans = new XslCompiledTransform();
   4: trans.Load(ds.CreateNavigator());
   5:  
   6: //create the output stream
   7: XmlTextWriter myWriter = new XmlTextWriter
   8:    ("result.xml", null);
   9:  
  10: // Transform the InfoPath form and save the XML into the stream for the part
  11: trans.Transform(this.MainDataSource.CreateNavigator(), null, myWriter);
  12: myWriter.Close() ; 

Các bạn sẽ thấy, kết quả thực hiện không khác so với sử dụng JScript. Bởi vì khi can thiệp vào các Event, Action trong InfoPath, chúng ta không thể sử dụng đồng thời cả JScript và C# cùng một lúc. Do đó, các bạn cần phải lựa chọn Programming Language cho InfoPath. Đối với các bài toàn phức tạp, chúng ta nên sử dụng C#, ngược lại các yêu cầu đơn giản chúng ta sử dụng JScript là một thuận lợi.

August 12, 2009

InfoPath: Custom save form using JScript

Filed under: InfoPath — basquang @ 11:10 AM

Đôi khi chúng ta cần save InfoPath file dưới một tên và folder đã được định sẵn. Bài viết này hướng dẫn các ban làm điều đó.

1. Mở InfoPath để thiết kế 1 form với một textbox control

2. Vào Tools –> Form Options và chọn “Save using custom code” và click on “Edit…” button

   1: function XDocument::OnSaveRequest(eventObj)
   2: {
   3:     try
   4:      {
   5:         //XDocument.UI.SetSaveAsDialogLocation("\\my\form\directory")
   6:         XDocument.UI.SetSaveAsDialogLocation("C:\\")
   7:         var strFileName = XDocument.DOM.selectSingleNode("/my:myFields/my:field1").text + ".xml"; 
   8:         XDocument.UI.SetSaveAsDialogFileName(strFileName);
   9:         eventObj.IsCancelled = eventObj.PerformSaveOperation();
  10:         eventObj.ReturnStatus = true;
  11:      } 
  12:      catch(e)
  13:      {
  14:         XDocument.UI.Alert("Error at OnSaveRequest: " + e.message);
  15:         eventObj.ReturnStatus = false;
  16:      }  
  17: }

3. Save Infopath form. Chúng ta có thể sẵn sàng test.

InfoPath Auto Submit to Local Folder using JScript

Filed under: InfoPath — basquang @ 10:53 AM

Khi sử dụng InfoPath, đôi khi chúng ta có nhu cầu tự động submit với filename là một field nào đó trên InfoPath form, hoặc là được đặt sẵn. Để thực hiện được điều này chúng ta có thể sử dụng C# code hoặc JScript. Bài viết này hướng dẫn các bạn thực hiện điều đó. Bài viết đề cập đến các kỹ thuật sau:

– Tự động submit infopath form sử dụng JScript code.

– Tự động save filename sử dụng một text field trên form

– Kiểm tra folder đã tồn tại hay chưa trước khi submit

– Sau khi submit mở luôn một form mới để nhập

1. Trước hết chúng ta kiểm tra Programming Language default của InfoPath form khi thiết kế sử dụng InfoPath thiết lập cho JScript

image

2. Chúng ta thiết kế một form đơn giản bao gồm một textbox và một button

image

3. Click chuột vào Submit button và chọn Action là Submit. Sau đó click on Submit Option… button.

4. Trong Submit Options dialog box, chọn “Allow users to submit this form” –> Chọn “Perform custom action using Code”. Trong “After submit” option, chọn “Create a new, blank form”. Sau đó click on “Edit Code…” button.

image

5. Chúng ta sử dụng JScript Code như sau để submit

   1: function XDocument::OnSubmitRequest(eventObj)
   2: {    
   3:     //Get the filename
   4:     var strFileName = XDocument.DOM.selectSingleNode("/my:myFields/my:field1").text + ".xml"; 
   5:     var xmlDoc = XDocument.DOM.xml;  
   6:     //create FSO Object
   7:     var objFSO = new ActiveXObject("Scripting.FileSystemObject");  
   8:     //Check the folder exist
   9:     if(!objFSO.FolderExists("C:\\InfoPath"))
  10:   {
  11:   //Create folder
  12:    objFSO.CreateFolder("C:\\InfoPath");
  13:   }            
  14:     //Create file
  15:     var tempFile = objFSO.CreateTextFile("C:\\InfoPath\\" + strFileName , true);  
  16:     //Save
  17:     tempFile.Write(xmlDoc);     
  18:     eventObj.ReturnStatus = true;
  19: }

6. Đảm bảo form được full trust

image 

7. Giờ các bạn sẵn sàng test form.

Note: Nếu chúng ta muốn lưu data sau khi submit vào thư mực hiện thời của .xsn file, chúng ta sử dụng câu lệnh:

var folder = fso.GetFolder(".");

để get current folder của .xsn file.

var folderPath = fso.GetFolder(".").path;

để lấy đường dẫn của thư mục hiện thời.

July 27, 2009

Convert an InfoPath 2007 form into a Word 2007 document using XSLT and C#

Filed under: InfoPath — basquang @ 9:52 AM

Tham khảo bài viết Convert an InfoPath 2007 form into a Word 2007 document using XSLT and C# để thực hiện việc Export InfoPath 2007 form data ra Word 2007. Chúng ta cần chú ý một số điểm sau:

– namespace của xsd phải có đủ trong xsl

– namespace trong w:document có đủ trong xsl:stylesheet của xsl

  • Open Microsoft Visual Studio 2005 and create a new InfoPath C# project.
  • Design an InfoPath form as shown in figure 1.

    Figure 1. InfoPath form in design mode.
  • The Main data source of the InfoPath form should resemble the following figure.

    Figure 2. Main data source of InfoPath form.
  • Create a docx file as shown in figure 3 and save it as template.docx. This Word 2007 document will be used as a template file to base your converted InfoPath forms on.

    Figure 3. The Word 2007 document to use as a template for converting InfoPath forms.
    The text ip_firstName, ip_lastName, ip_website, and table_cell_1 are used as placeholders just to make it easier later on to locate the positions in the XSLT stylesheet where to place references to the InfoPath form fields. Note that table_cell_1 is contained within a table. This table will be used to show the items from the Repeating Table on the InfoPath form.
  • Open Windows Explorer and browse to the template.docx file.
  • Copy template.docx, paste it, and rename it to template.zip.
  • Extract the files from the template.zip file.

    Figure 4. Contents of template.zip.
  • Double-click on the word folder to open it.

    Figure 5. Contents of the word folder in template.zip.
  • Open the document.xml file in Notepad and save it as transform.xsl in the same folder where template.docx is located.
  • Replace

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    which is located at the beginning of the transform.xsl file with

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform&quot; version="1.0">
    <xsl:output method="xml" />
    <xsl:template match="/">

  • Append the following XSL tags to the end of the transform.xsl file:

    </xsl:template>
    </xsl:stylesheet>

  • Switch to Microsoft Visual Studio 2005, go to the Solution Explorer, open the myschema.xsd file to view its code, copy all of the namespaces defined for the form (except for the default and xsd namespaces), and paste them as attributes of the xsl:stylesheet node in the transform.xsl file. The beginning xsl:stylesheet tag should now look something like:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform&quot; version="1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot;
    xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2006-12-31T07:11:15&quot;
    xmlns:xd="http://schemas.microsoft.com/office/infopath/2003&quot;

  • Copy all of the namespaces defined in the w:document node in the transform.xsl file, and paste them as attributes of the xsl:stylesheet node in the transform.xsl file. The beginning xsl:stylesheet tag should now look something like:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform&quot; version="1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot;
    xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2006-12-31T07:11:15&quot;
    xmlns:xd="http://schemas.microsoft.com/office/infopath/2003&quot; xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture&quot; xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main&quot;
    xmlns:ve="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    xmlns:o="urn:schemas-microsoft-com:office:office"
    xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships&quot;
    xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math&quot;
    xmlns:v="urn:schemas-microsoft-com:vml"
    xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing&quot;
    xmlns:w10="urn:schemas-microsoft-com:office:word"
    xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main&quot;
    xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml&quot;

  • Search for ip_firstName in the transform.xsl file and replace it with

    <xsl:value-of select="my:myFields/my:firstName" />

  • Search for ip_lastName in the transform.xsl file and replace it with

    <xsl:value-of select="my:myFields/my:lastName" />

  • Search for ip_website in the transform.xsl file and replace it with

    <xsl:value-of select="my:myFields/my:website" />

  • Search for table_cell_1 in the transform.xsl file and replace it with

    <xsl:value-of select="my:name" />

  • Search for the last </w:tblGrid> tag and append the following XSL code

    <xsl:for-each select="my:myFields/my:countries/my:country">

  • Search for the last </w:tr> tag and append the following XSL code

    </xsl:for-each>

  • The final transform.xsl file should now look something like this file.
  • Open the InfoPath form in design mode.
  • Select the Data > Data Connections… menu item.
  • Click on the Add… button on the Data Connections dialog box.
  • Select the Receive data option button and click on the Next > button.
  • Select the XML document option button and click on the Next > button.
  • Click on the Browse… button to navigate to and select the XSL file you created in step 20.
    Tip: Select All Files (*.*) in the Files of type drop-down list box to be able to see the XSLT file.
  • Click on the Next > button after you have selected the file and returned to the Data Connection Wizard dialog box.
  • Select Include the data as a resource file in the form template or template part and click on the Next > button.
  • Make sure that the Automatically retrieve data when form is opened checkbox is selected and then click on the Finish button.
  • Click on the Close button to close the Data Connections dialog box.
  • Go to the Solution Explorer window, click on the References node, and add a reference to the WindowsBase DLL that comes with the Microsoft .NET Framework 3.0.
  • Double-click on the button to open its Properties dialog box.
  • Click on the Edit Form Code… button and add the following code in the Clicked event handler that InfoPath created for you:

    // Define variables for the word template to use and file to create
    string wordTemplateFilePath = @"C:\InfoPath\ConvertToWord2007\template.docx";
    string wordPrintFilePath = @"C:\InfoPath\ConvertToWord2007\wordprint.docx";
    // Copy the template to create a new docx file
    File.Copy(wordTemplateFilePath, wordPrintFilePath, true);
    // Crack open the package
    Package packWordPrint = Package.Open(wordPrintFilePath, FileMode.Open, FileAccess.ReadWrite);
    // Retrieve the document.xml part of the new docx file
    PackagePart part = packWordPrint.GetPart(new Uri("/word/document.xml", UriKind.Relative));
    // Retrieve the xsl to use to transform the InfoPath form into document.xml
    DataSource ds = this.DataSources["transform"];
    XslCompiledTransform trans = new XslCompiledTransform();
    trans.Load(ds.CreateNavigator());
    // Create a StreamWriter to be able to write to the stream of the part
    using (StreamWriter partStream = new StreamWriter(part.GetStream(FileMode.Open, FileAccess.Write)))
    {
    // Transform the InfoPath form and save the XML into the stream for the part
    trans.Transform(this.MainDataSource.CreateNavigator(), null, partStream);
    // Close the stream of the part
    partStream.Close();
    }
    // Write changes to the package
    packWordPrint.Flush();
    // Close the package
    packWordPrint.Close();
    // Open the new docx file in Word 2007
    Process proc = new Process();
    proc.EnableRaisingEvents = false;
    proc.StartInfo.FileName = "winword";
    proc.StartInfo.Arguments = wordPrintFilePath;
    proc.Start();

    NOTE: Remember to change the path to the template.docx file as required by your own situation.

  • Add the following using statements to your form’s code file:

    using System.IO;
    using System.IO.Packaging;
    using System.Diagnostics;
    using System.Xml.Xsl;

  • Give your InfoPath form Full Trust by going to Tools > Form Options and selecting the Security and Trust tab. And sign your InfoPath form with a digital certificate.
  • Build your InfoPath project.
  • Export InfoPath form to Word 2003 document sử dụng XSLT và XPath

    Filed under: InfoPath — basquang @ 9:15 AM

    Khi làm việc với InfoPath, nhiều khi chúng ta có nhu cầu Export ra file .doc để người dùng không phải IT pro có thể chỉnh sửa theo ý mình. Bài viết Convert an InfoPath form into a Word 2003 document and send this as an attachment in an e-mail trình bày cho các bạn cách để thực hiện điều đó. Tuy nhiên, bài viết này mới chỉ dừng lại ở việc Export giữ liệu tĩnh, nghĩa là khi chúng ta thay đổi nội dung trên form, thì khi export ra file .doc lại không thay đổi.

    Bài viết này trình bày cho các bạn một cách đầy đủ, cách để Export InfoPath form ra Word 2003 (chú ý, là Word 2003. Để export ra Word 2007 tôi sẽ trình bày trong một bài viết khác).

    1. Thiết kế một InfoPath form như sau:

    image

    2. Fill form này và lưu thành file Form1.xml

    image

    3. Mở file bạn vừa save từ InfoPath form (Form1.xml) trên Word. Sau đó tiến hành thêm nội dung, chỉnh sửa giao diện của file xml này trên Word.

    Sau khi format xong, chúng ta chọn File –> Save As. Trong hộp thoại Save As, chú ý là chúng ta bỏ chọn Save data only checkbox và đặt tên file là Form1_1.xml

    image image

    4. Việc tiếp theo là chúng ta download và cài đặt WordML Transform Inference Tool. Sau đó chúng ta sử dụng cmd để thực thi việc tạo XSLT file như sau:

    WML2XSLT.EXE "C:\InfoPath\ExportToWord2003\Form1_1.xml" -o "C:\InfoPath\ExportToWord2003\XMLToWordML.xsl"

    Chúng ta bấm Select All và click Ok nếu hộp thoại “Select namespaces” xuất hiện.

    image 

    5. Quay trở lại InfoPath trong trạng thái Design mode. Chúng ta chọn File –> Save as source files

    image

    6. Mở myschema.xsd trong SourceFile folder vừa export từ InfoPath, và XMLToWordML.xsl vừa mới tạo từ tool, bằng một Text editor nào đó. Sau đó chúng ta copy 2 namespace từ xsd sang xsl như sau:

    myschema.xsd
     
    <xsd:schema targetNamespace="http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-07-27T07:17:59" 
    ...
    xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-07-27T07:17:59" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    ...
    >

    XMLToWordML.xsl sau khi copy

    <xsl:stylesheet version="1.0" 
    xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-07-27T07:17:59" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    ...
    >

    7. Tiếp theo chúng ta tìm đến các nội dung: “Quang” và “Nguyen Ba” được bao trong thẻ <xsl:text>….</xsl:text> của xsl, để thay thế nó bằng XPath như sau.

    <xsl:text>Quang</xsl:text> –> <xsl:value-of select="my:myFields/my:firstName" />

    <xsl:text>Nguyen Ba</xsl:text> –> <xsl:value-of select="my:myFields/my:lastName" />

    <xsl:text>http://basquang.spaces.live.com</xsl:text> –> <xsl:value-of select="my:myFields/my:website" />

    Sau đó chúng ta save file này.

    8. Quay trở lại InfoPath form ở dạng Design mode. Chúng ta chọn Tools –> Data Connections… và chọn Add button. Trong hộp thoại Data Connection Wizard chúng ta chọn “Receive Data” và trỏ tới file XMLToWordML.xsl và để mặc định các lựa chọn của Wizard. Chú ý tên cho data connection là XMLToWordML

    image

    9. Vào Tools –> Options để kiểm tra Default programming language khi design form bằng InfoPath là được thiết lập cho JScript

    image

    10.  Click đúp vào “Export to Word 2003” button và chọn Edit Form Code. Sau đó Add đoạn code sau trong OnClick event và Save InfoPath.

    image image

    var formInXML = XDocument.DOM;
    var xslXMLToWordML = XDocument.GetDOM("XMLToWordML"); 
    var formInWordML = formInXML.transformNode(xslXMLToWordML);
    var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.async = false;
    xmlDoc.loadXML(formInWordML);
    xmlDoc.save("C:\\InfoPath\\InfoPathFormInWordML.xml");
    var wordApp = new ActiveXObject("Word.Application");
    wordApp.Documents.Open("C:\\InfoPath\\InfoPathFormInWordML.xml");
    wordApp.Visible = true;

     

    11. Mở Tools –> Form Options –> Security and Trust  để chọn Full Trust và Sign this form

    image

    12. Giờ chúng ta sẵn sàng sử dụng Export InfoPath to Word 2003 function

    image

    June 15, 2009

    InfoPath: Drop-Down List Changed, Switch View

    Filed under: InfoPath — basquang @ 5:11 AM

    Web know, switch available in Button rule. Sometime, we need to switch view when InfoPath form data changed like Drop-Down List Changed Event. What’re We going to do?

    We must implement FormEvents.ContextChanged and DropDown Changed. In FormEvents.ContextChanged we call

    ViewInfos.SwitchView(viewname);

    Here is my code

    public void InternalStartup()
            {         
                EventManager.FormEvents.ContextChanged += new ContextChangedEventHandler(FormEvents_ContextChanged);
                EventManager.XmlEvents["/my:DoanhNghieps/my:loaiHinhHoatDong"].Changed += new XmlChangedEventHandler(loaiHinhHoatDong_Changed);
            }

            public void FormEvents_ContextChanged(object sender, ContextChangedEventArgs e)
            {          
                if (canRedirect)
                {
                    canRedirect = false;
                    ViewInfos.SwitchView("CN");
                }
            }
            private bool canRedirect = false;
            public void loaiHinhHoatDong_Changed(object sender, XmlEventArgs e)
            {
                // Write your code here to change the main data source.
                canRedirect = true;           
            }
           

    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.

    Blog at WordPress.com.