If you have worked with InfoPath, you'll agree one has to come
up with different techniques and tricks to implement solutions
that are not available out-of-the-box.
In this article, I present a technique using which you can copy
file attachments from one section to another. There are
different scenarios in which you may want to do this. For
example, consider a situation where you want to restrict users
from deleting attachments once uploaded. Properties of file
attachment control can only be set at design time and these
properties once set cannot be changed dynamically. You can
either allow users to insert/delete files or disallow them
inserting or deleting files. Solution is to use two attachment
controls and copy the content of one control to the other when
user saves the form. One control will allow inserting/deleting
files. The control will not allow inserting or deleting files
and if you want to upload multiple files, then put the file
attachment control in a repeating section. In this case, the
read-only file attachment control should also be put in a
repeating section. The source and destination data nodes
hierarchy should be same otherwise copying of content will not
work.
1. Start InfoPath 2007. Click "Data Source" in "Design Tasks".

Fig 1: Data Source (Design Tasks)
2. Right-click "myFields" and select "Add..." from the
menu.

Fig 2: Add node
3. Add name "group1" and from "Type" select "Group". Click OK.

Fig 3: Add group
4. Right-click newly added group "group1" and select "Add..."
from the menu. Enter "repGroup1" in the "Name" field and
select "Group" from the "Type" field. Check "Repeating" checkbox
at the bottom. This is important because this will be a
repeating group. This repeating group will hold multiple file
attachment controls.

Fig 4: Add repeating group
5. Drag repeating group "repGroup1" and drop it on the form.
This will insert a repeating section in the form.
6. Click "Design Tasks" and then click "Controls". From the
controls panel, select "File Attachment" control and add it to
the repeating section. Make sure the cursor is inside the
repeating section and then double-click "File Attachment"
control. This will insert the control in the repeating section.
7. Click "Design Tasks" again and select "Data Source".
Right-click "myFields" and select "Add...". Enter "group2" in
the "Name" field and select "Group" in the "Type" field. Click
Ok. This will create a new non-repeating group. Our goal is to
create a new section with file attachment control but in this
case, we will now allow inserting or deleting files. In other
words, it will be a read-only section with read-only file
attachment control.

Fig 5: Add destination group
8. Right-click "repGroup1" and select "Reference..." from the
menu. Select "group2" from the list and click "OK". This will
add a repeating group and a data node in the "group2" node.
9. Drag "repGroup1" from "group2" and drop it on the form.
Select repeating section from the menu that opens. This will add
an empty repeating section on the form. Drag "field1" from
"group2" and drop it inside the newly added repeating section.
Now you have two identical repeating sections in the form.
Advantage of using repeating section is, user can add as many
file attachments as he or she likes.
10. Right-click second repeating section and select "Repeating
Section Properties..." from the options menu. Uncheck "Allow
users to insert and delete the sections". Click "OK".
11. Right-click second file attachment control and select "File
Attachment Properties..." from the menu. Uncheck "Allow the user
to browse, delete, and replace files" and click "OK".

Fig 6: Make file attachment read-only
12. Add a button to the form (Design Tasks > Controls).
13. Select "Form Options" from the "Tools" menu.

Fig 7: Form Options
14. Select "Programming" category. Select "C#" in the "Form
template code language". Click "OK".

Fig 8: Select programming language
15. Double-click button and select "Edit Form Code". You will be
prompted to save the form if you had not saved it already. Click
"Ok". Give an appropriate name to your form. I kept the default
name "Template1.xsn". This will create a new C# project for you.
The location of the project, by default, will be as follows:
C:\Documents and Settings\Administrator\My Documents\InfoPath
Projects\Template11\Template1.csproj
Note, you can change this location by going to Tools > Form
Options and then by selecting "Programming" from the categories.
Change the location in the field called "Project location for VB
and C# code". This field is located at the bottom.
16. Copy following code to the project:
|
private
void
CopyAttachments()
{
string srcXPath
= "/my:myFields/my:group1";
string
destXPath = "/my:myFields/my:group2";
string
srcNodeXPath = "/my:myFields/my:group1/repGroup1";
XPathNavigator
source = this.CreateNavigator().SelectSingleNode(srcXPath,
this.NamespaceManager);
XPathNavigator
dest = this.CreateNavigator().SelectSingleNode(destXPath,
this.NamespaceManager);
if
(dest.MoveToAttribute("nil",
"http://www.w3.org/2001/XMLSchema-instance"))
dest.DeleteSelf();
if
(source.InnerXml.Contains("xsi:nil="))
{
//Do nothing
}
else
{
if
(dest.InnerXml.Contains("xsi:nil="))
{
dest.InnerXml = source.InnerXml;
}
else
{
dest.InnerXml += source.InnerXml;
}
//clear source
files
XPathNavigator
srcFiles = this.CreateNavigator().SelectSingleNode(srcNodeXPath,
this.NamespaceManager);
if
(IsGridDirty(srcNodeXPath))
{
XPathNodeIterator
Node_To_Be_Deleted =
this.CreateNavigator().Select(srcNodeXPath,
NamespaceManager);
string
groupResults = srcNodeXPath;
XPathNavigator
firstItem;
XPathNavigator
lastItem;
if
(Node_To_Be_Deleted.Count > 1)
{
firstItem = srcFiles.SelectSingleNode(groupResults +
"[1]",
NamespaceManager);
lastItem = srcFiles.SelectSingleNode(groupResults +
"[position()=last()]",
NamespaceManager);
firstItem.DeleteRange(lastItem);
//clean up
local variables
lastItem = null;
firstItem =
null;
}
else
if
(Node_To_Be_Deleted.Count == 1)
{
firstItem = srcFiles.SelectSingleNode(groupResults +
"[1]",
NamespaceManager);
firstItem.DeleteSelf();
}
//clean up
Node_To_Be_Deleted =
null;
}
//clean up
srcFiles = null;
}
}
private
bool
IsGridDirty(string
ControlName)
{
try
{
//This function
checks whether the Results node has any items or not,
returns true if the number of items is greater than 0.
XPathNavigator
_DOM = this.MainDataSource.CreateNavigator();
XPathNodeIterator nodes =
_DOM.Select(ControlName,
this.NamespaceManager);
XPathNavigator
nodesNavigator = nodes.Current;
XPathNodeIterator nodesText =
nodesNavigator.SelectDescendants(XPathNodeType.Text,
false);
int
counter = 0;
while
(nodesText.MoveNext())
{
if
(nodesText.Current.NodeType ==
XPathNodeType.Text)
{
//if (nodesText.Current.Name
== "Section5_Selected" && (nodesText.Current.Value ==
"true" || nodesText.Current.Value == "false" ||
nodesText.Current.Value == "" || nodesText.Current.Value
== "blank"))
//{
counter += 1;
//}
}
}
//clean up
nodesText =
null;
nodesNavigator =
null;
nodes = null;
_DOM = null;
//return count
if
(counter > 0)
{
return
true;
}
else
{
return
false;
}
}
catch
(Exception
ex)
{
return
false;
}
}
|
Check these lines:
string
srcXPath = "/my:myFields/my:group1";
string
destXPath = "/my:myFields/my:group2";
string
srcNodeXPath = "/my:myFields/my:group1/repGroup1";
Paths should be correct. srcXPath contains the xPath of the
source group, that is, group1. destXPath contains the xPath for
the destination group, that is, group2. srcNodeXPath contains
the xPath of first repeating group.
16. Call "CopyAttachments()" in the button's click:
|
public
void
CTRL5_5_Clicked(object
sender,
ClickedEventArgs e)
{
CopyAttachments();
}
|
17. Save the project, compile it and publish the form. Add
attachments to the first repeating section and click the button.
The files will be copied to the second repeating section and
cleared from the first repeating section. Now users cannot
delete files from the second repeating section. Usually this
function is called when the form is submitted because before the
form is saved or submitted, user can change the files.
|