예제 #1
0
        public static void replaceXmlDoc(Office.CustomXMLPart cxp, String newContent)
        {
            /* Office.CustomXMLNode node = cxp.SelectSingleNode("/");
            // gives you #document,
            // but you can't get the root node from it?

               //node = cxp.SelectSingleNode("/mypart");
             */

            Office.CustomXMLNode node = cxp.SelectSingleNode("/node()");
            //log.Debug(node.XML);
            //log.Debug(node.XPath);

            Office.CustomXMLNode parent = node.ParentNode;

            log.Debug(parent.BaseName);

            //parent.ReplaceChildNode(node, "mynewnode", "", Office.MsoCustomXMLNodeType.msoCustomXMLNodeElement, "");

            parent.ReplaceChildSubtree(newContent, node);

            //parent.RemoveChild(node); //doesn't work

            //parent.AppendChildSubtree("<mynewpart><blagh/></mynewpart>");

            node = cxp.SelectSingleNode("/");
            log.Debug(node.XML);
        }
        public void init(
            Office.CustomXMLPart answersPart,
            List<Word.ContentControl> relevantRepeats,
            questionnaire questionnaire, 
            string questionID,
            XPathsPartEntry xppe)
        {
            List<Office.CustomXMLNode> commonAncestors =null;
            foreach (Word.ContentControl repeat in relevantRepeats)
            {
                log.Info("considering relevantRepeat cc " + repeat.ID + " " + repeat.Tag);
                TagData repeatTD = new TagData(repeat.Tag);
                string repeatXPathID = repeatTD.getRepeatID();
                xpathsXpath repeatXP = xppe.getXPathByID(repeatXPathID);
                Office.CustomXMLNode repeatNode = answersPart.SelectSingleNode(repeatXP.dataBinding.xpath).ParentNode;

                if (commonAncestors == null)
                {
                    // First entry, so init
                    // Make a list of the ancestors of the
                    // first repeat.
                    commonAncestors = new List<Microsoft.Office.Core.CustomXMLNode>();
                    commonAncestors.Add(repeatNode);
                    log.Info("Added to common ancestors " + CustomXMLNodeHelper.getAttribute(repeatNode, "qref"));
                    addAncestors(commonAncestors, repeatNode);
                }
                else
                {
                    // cross off that list anything
                    // which isn't an ancestor of the other repeats.
                    List<Microsoft.Office.Core.CustomXMLNode> whitelist = new List<Microsoft.Office.Core.CustomXMLNode>();
                    whitelist.Add(repeatNode);
                    addAncestors(whitelist, repeatNode);
                    removeNonCommonAncestor(commonAncestors, whitelist);
                }

                if (commonAncestors.Count == 0) break;
            }
            if (commonAncestors == null)
            {
                    commonAncestors = new List<Microsoft.Office.Core.CustomXMLNode>();
            }

            // Is it OK where it is?
            // Yes - if it is top level
            log.Debug(questionID + " --> " + xppe.getXPathByQuestionID(questionID).dataBinding.xpath);
            // eg /oda:answers/oda:repeat[@qref='rpt1']/oda:row[1]/oda:answer[@id='qa_2']
            OkAsis = (xppe.getXPathByQuestionID(questionID).dataBinding.xpath.IndexOf("oda:repeat") < 0);
            Microsoft.Office.Core.CustomXMLNode currentPos = null; // so we can highlight existing choice
            // Yes - if it is a child of common ancestors
            if (OkAsis)
            {
                log.Debug("its top level");
            }
            else
            {
                foreach (Microsoft.Office.Core.CustomXMLNode currentNode in commonAncestors)
                {
                    Microsoft.Office.Core.CustomXMLNode selection =
                        currentNode.SelectSingleNode("oda:row[1]/oda:answer[@id='" + questionID + "']");
                    if (selection != null)
                    {
                        log.Debug("found it");
                        OkAsis = true;
                        currentPos = currentNode;
                        break;
                    }
                }
            }

            // Now make the tree from what is left in commonAncestors

            root = new TreeNode("Ask only once");
            this.treeViewRepeat.Nodes.Add(root);

            TreeNode thisNode = null;
            TreeNode previousNode = null;
            treeViewRepeat.HideSelection = false; // keep selection when focus is lost

            TreeNode nodeToSelect = null;

            foreach (Microsoft.Office.Core.CustomXMLNode currentNode in commonAncestors)
            {
                // Find the question associated with this repeat
                string rptQRef = CustomXMLNodeHelper.getAttribute(currentNode, "qref");
                    //currentNode.Attributes[1].NodeValue;
                question q = questionnaire.getQuestion(rptQRef);
                if (q == null)
                {
                    log.Error("no question with id " + rptQRef);
                }
                thisNode = new TreeNode(q.text);
                thisNode.Tag = rptQRef;

                if (currentNode == currentPos)
                {
                    nodeToSelect = thisNode;
                }

                if (previousNode == null)
                {
                    // Check the innermost (may be overridden below by what level user already had, if possible)
                    this.treeViewRepeat.SelectedNode = thisNode;
                }
                else
                {
                    thisNode.Nodes.Add(previousNode);
                }
                previousNode = thisNode;

            }

            if (thisNode != null)
            {
                root.Nodes.Add(thisNode);
            }
            treeViewRepeat.ExpandAll();

            if (nodeToSelect != null)
            {
                this.treeViewRepeat.SelectedNode = nodeToSelect;
                originalValue = thisNode;
            }
            else if (OkAsis)
            {
                originalValue = root;
                this.treeViewRepeat.SelectedNode = root;
            }
        }
        /// <summary>
        /// When an answer's vary in repeat changes:
        /// - move the node
        /// - change its xpath
        /// - change the databinding in all relevant controls
        /// </summary>
        /// <param name="questionID"></param>
        /// <param name="xp"></param>
        /// <param name="answersPart"></param>
        public void moveIfNecessary(string questionID, xpathsXpath xp, 
            Office.CustomXMLPart answersPart)
        {
            string varyInRepeat = getVaryingRepeat( );
            if (varyInRepeat == null)
            {
                // make the answer top level and we're done.
                NodeMover nm = new NodeMover();
                nm.Move(xp.dataBinding.xpath, "/oda:answers");
                nm.adjustBinding(thisQuestionControls, "/oda:answers", questionID);
            }
            else
            {
                // Move it to the selected repeat
                // get the node corresponding to the repeat's row
                Office.CustomXMLNode node = answersPart.SelectSingleNode("//oda:repeat[@qref='" + varyInRepeat + "']/oda:row[1]");
                if (node == null)
                {
                    log.Error("no node for nested repeat " + varyInRepeat);
                }
                string toRepeat = NodeToXPath.getXPath(node);
                NodeMover nm = new NodeMover();
                nm.Move(xp.dataBinding.xpath, toRepeat);
                nm.adjustBinding(thisQuestionControls, toRepeat, questionID);

            }
        }
        public void treeView_ItemDrag(object sender, ItemDragEventArgs e,
            ControlTreeView controlTreeView,
            ControlMain controlMain, 
            Word.Document CurrentDocument, 
            Office.CustomXMLPart CurrentPart, XmlDocument OwnerDocument,
            bool _PictureContentControlsReplace)
        {
            object missing = System.Type.Missing;

            TreeNode tn = (TreeNode)e.Item;

            if (tn == null)
            {
                Debug.Fail("no tn");
                return;
            }

            //check if this is something we can drag
            if (((XmlNode)tn.Tag).NodeType == XmlNodeType.ProcessingInstruction
                || ((XmlNode)tn.Tag).NodeType == XmlNodeType.Comment)
                return;
            if (controlMain.modeControlEnabled == false // ie always mode bind
                || controlMain.controlMode1.isModeBind())
            {
                if (!ControlTreeView.IsLeafNode(tn)
                    || ((XmlNode)tn.Tag).NodeType == XmlNodeType.Text && !ControlTreeView.IsLeafNode(tn.Parent))
                    return;
            } // repeats and conditions; let them drag any node

            //get an nsmgr
            NameTable nt = new NameTable();

            //generate the xpath and the ns manager
            XmlNamespaceManager xmlnsMgr = new XmlNamespaceManager(nt);
            string strXPath = Utilities.XpathFromXn(CurrentPart.NamespaceManager, (XmlNode)tn.Tag, true, xmlnsMgr);
            log.Info("Dragging XPath: " + strXPath);

            string prefixMappings = Utilities.GetPrefixMappings(xmlnsMgr);

            // OpenDoPE
            TagData td = new TagData("");
            String val = ((XmlNode)tn.Tag).InnerText;

            DesignMode designMode = new OpenDoPEModel.DesignMode(CurrentDocument);

            // Special case for pictures, since drag/drop does not seem
            // to work properly (the XHTML pasted doesn't do what it should?)
            bool isPicture = ContentDetection.IsBase64Encoded(val);

            if (isPicture && !_PictureContentControlsReplace)
            {
                designMode.Off();
                log.Debug("Special case handling for pictures..");

                // Selection can't be textual content, so ensure it isn't.
                // It is allowed to be a picture, so in the future we could
                // leave the selection alone if it is just a picture.
                Globals.ThisAddIn.Application.Selection.Collapse(ref missing);
                // Are they dragging to an existing picture content control
                Word.ContentControl picCC = ContentControlMaker.getActiveContentControl(CurrentDocument, Globals.ThisAddIn.Application.Selection);
                try
                {
                    if (picCC == null
                        || (picCC.Type != Word.WdContentControlType.wdContentControlPicture))
                    {
                        picCC = CurrentDocument.ContentControls.Add(
                            Word.WdContentControlType.wdContentControlPicture, ref missing);
                        designMode.restoreState();
                    }
                }
                catch (COMException ce)
                {
                    // Will happen if you try to drag a text node onto an existing image content control
                    log.Debug("Ignoring " + ce.Message);
                    return;
                }
                XPathsPartEntry xppe = new XPathsPartEntry(controlMain.model);
                xppe.setup(null, CurrentPart.Id, strXPath, prefixMappings, false);
                xppe.save();

                td.set("od:xpath", xppe.xpathId);
                picCC.Tag = td.asQueryString();

                picCC.Title = "Data value: " + xppe.xpathId;
                picCC.XMLMapping.SetMappingByNode(Utilities.MxnFromTn(tn, CurrentPart, true));
                return;
            }

            log.Debug("\n\ntreeView_ItemDrag for WdSelectionType " + Globals.ThisAddIn.Application.Selection.Type.ToString());

            bool isXHTML = false;
            bool isFlatOPC = ContentDetection.IsFlatOPCContent(val);
            if (!isFlatOPC) isXHTML = ContentDetection.IsXHTMLContent(val);

            if (Globals.ThisAddIn.Application.Selection.Type
                != Microsoft.Office.Interop.Word.WdSelectionType.wdSelectionIP)
            {
                // ie something is selected, since "inline paragraph selection"
                // just means the cursor is somewhere inside
                // a paragraph, but with nothing selected.

                designMode.Off();

                // Selection types: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.wdselectiontype(v=office.11).aspx
                log.Debug("treeView_ItemDrag fired, but interpreted as gesture for WdSelectionType " + Globals.ThisAddIn.Application.Selection.Type.ToString());

                Word.ContentControl parentCC = ContentControlMaker.getActiveContentControl(CurrentDocument,
                            Globals.ThisAddIn.Application.Selection);

                // Insert bind | condition | repeat
                // depending on which mode button is pressed.
                if (controlMain.modeControlEnabled == false // ie always mode bind
                    || controlMain.controlMode1.isModeBind())
                {
                    log.Debug("In bind mode");
                    Word.ContentControl cc = null;

                    try
                    {
                        if (isFlatOPC || isXHTML
                            || (isPicture && _PictureContentControlsReplace))
                        {

                            // Rich text
                            if (parentCC != null
                                && ContentControlOpenDoPEType.isBound(parentCC))
                            {
                                // Reuse existing cc
                                cc = ContentControlMaker.MakeOrReuse(true, Word.WdContentControlType.wdContentControlRichText, CurrentDocument,
                                    Globals.ThisAddIn.Application.Selection);
                            }
                            else
                            {
                                // Make new cc
                                cc = ContentControlMaker.MakeOrReuse(true, Word.WdContentControlType.wdContentControlRichText, CurrentDocument,
                                    Globals.ThisAddIn.Application.Selection);
                            }

                            if (isFlatOPC)
                            {
                                log.Debug(".. contains block content ");
                                // Ensure block level
                                Inline2Block i2b = new Inline2Block();
                                cc = i2b.convertToBlockLevel(cc, false, true);

                                if (cc == null)
                                {
                                    MessageBox.Show("Problems inserting block level WordML at this location.");
                                    return;
                                }

                            }
                            else if (isXHTML // and thus not picture
                             && Inline2Block.containsBlockLevelContent(val))
                            {
                                log.Debug(".. contains block content ");
                                // Ensure block level
                                Inline2Block i2b = new Inline2Block();
                                cc = i2b.convertToBlockLevel(cc, false, true);

                                if (cc == null)
                                {
                                    MessageBox.Show("Problems inserting block level XHTML at this location.");
                                    return;
                                }
                            }

                        }
                        else
                        {

                            // Plain text
                            if (parentCC != null
                                && ContentControlOpenDoPEType.isBound(parentCC))
                            {
                                // Reuse existing cc
                                cc = ContentControlMaker.MakeOrReuse(true, Word.WdContentControlType.wdContentControlText, CurrentDocument,
                                    Globals.ThisAddIn.Application.Selection);
                            }
                            else
                            {
                                // Make new cc
                                cc = ContentControlMaker.MakeOrReuse(false, Word.WdContentControlType.wdContentControlText, CurrentDocument,
                                    Globals.ThisAddIn.Application.Selection);
                            }
                            cc.MultiLine = true;
                            // Is a text content control always run-level?
                            // No, not if you have a single para selected and you do drag gesture
                            // (or if you remap a rich text control)
                        }
                    }
                    catch (Exception ex)
                    {
                        log.Error("Couldn't add content control: " + ex.Message);
                        return;
                    }

                    XPathsPartEntry xppe = new XPathsPartEntry(controlMain.model);
                    xppe.setup(null, CurrentPart.Id, strXPath, prefixMappings, true);
                    xppe.save();

                    td.set("od:xpath", xppe.xpathId);

                    if (isFlatOPC)
                    {
                        // <?mso-application progid="Word.Document"?>
                        // <pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">

                        td.set("od:progid", "Word.Document");
                        cc.Title = "Word: " + xppe.xpathId;
                        //cc.Range.Text = val; // don't escape it
                        cc.Range.InsertXML(val, ref missing);

                    }
                    else if (isXHTML)
                    {
                        td.set("od:ContentType", "application/xhtml+xml");
                        cc.Title = "XHTML: " + xppe.xpathId;
                        cc.Range.Text = val; // don't escape it

                    }
                    else if (isPicture)
                    {

                        PictureUtils.setPictureHandler(td);
                        cc.Title = "Image: " + xppe.xpathId;

                        string picContent = CurrentPart.SelectSingleNode(strXPath).Text;
                        PictureUtils.pastePictureIntoCC(cc, Convert.FromBase64String(picContent));

                    }
                    else
                    {
                        cc.XMLMapping.SetMappingByNode(Utilities.MxnFromTn(tn, CurrentPart, true));

                        string nodeXML = cc.XMLMapping.CustomXMLNode.XML;
                        log.Info(nodeXML);
                        cc.Title = "Data value: " + xppe.xpathId;
                    }

                    cc.Tag = td.asQueryString();

                    designMode.restoreState();

                }
                else if (controlMain.controlMode1.isModeCondition())
                {

                    log.Debug("In condition mode");
                    Word.ContentControl cc = null;
                    try
                    {
                        // always make new
                        cc = ContentControlMaker.MakeOrReuse(false, Word.WdContentControlType.wdContentControlRichText, CurrentDocument, Globals.ThisAddIn.Application.Selection);
                    }
                    catch (Exception ex)
                    {
                        log.Error("Couldn't add content control: " + ex.Message);
                        return;
                    }
                    ConditionsPartEntry cpe = new ConditionsPartEntry(controlMain.model);
                    cpe.setup(CurrentPart.Id, strXPath, prefixMappings, true);
                    cpe.save();

                    cc.Title = "Conditional: " + cpe.conditionId;
                    // Write tag
                    td.set("od:condition", cpe.conditionId);
                    cc.Tag = td.asQueryString();

                    designMode.On();

                }
                else if (controlMain.controlMode1.isModeRepeat())
                {
                    log.Debug("In repeat mode");
                    Word.ContentControl cc = null;
                    try
                    {
                        // always make new
                        cc = ContentControlMaker.MakeOrReuse(false, Word.WdContentControlType.wdContentControlRichText, CurrentDocument, Globals.ThisAddIn.Application.Selection);
                    }
                    catch (Exception ex)
                    {
                        log.Error("Couldn't add content control: " + ex.Message);
                        return;
                    }

                    // Need to drop eg [1] (if any), so BetterForm-based interactive processing works
                    if (strXPath.EndsWith("]"))
                    {
                        strXPath = strXPath.Substring(0, strXPath.LastIndexOf("["));
                        log.Debug("Having dropped '[]': " + strXPath);
                    }

                    XPathsPartEntry xppe = new XPathsPartEntry(controlMain.model);
                    xppe.setup("rpt", CurrentPart.Id, strXPath, prefixMappings, false); // no Q for repeat
                    xppe.save();

                    cc.Title = "Repeat: " + xppe.xpathId;
                    // Write tag
                    td.set("od:repeat", xppe.xpathId);
                    cc.Tag = td.asQueryString();

                    designMode.On();
                }

                return;
            } // end if (Globals.ThisAddIn.Application.Selection.Type != Microsoft.Office.Interop.Word.WdSelectionType.wdSelectionIP)

            // Selection.Type: Microsoft.Office.Interop.Word.WdSelectionType.wdSelectionIP
            // ie cursor is somewhere inside a paragraph, but with nothing selected.
            log.Info("In wdSelectionIP specific code.");

            // leave designMode alone here

            // Following processing uses clipboard HTML to implement drag/drop processing
            // Could avoid dealing with that (what's the problem anyway?) if they are dragging onto an existing content control, with:
            //Word.ContentControl existingCC = ContentControlMaker.getActiveContentControl(CurrentDocument, Globals.ThisAddIn.Application.Selection);
            //if (existingCC != null) return;
            // But that stops them from dragging any more content into a repeat.

            string title = "";
            string tag = "";
            bool needBind = false;

            log.Debug(strXPath);
            Office.CustomXMLNode targetNode = CurrentPart.SelectSingleNode(strXPath);
            string nodeContent = targetNode.Text;
            // or ((XmlNode)tn.Tag).InnerXml

            // Insert bind | condition | repeat
            // depending on which mode button is pressed.
            if (controlMain.modeControlEnabled == false // ie always mode bind
                || controlMain.controlMode1.isModeBind())
            {
                log.Debug("In bind mode");
                // OpenDoPE: create w:tag=od:xpath=x1
                // and add XPath to xpaths part
                XPathsPartEntry xppe = new XPathsPartEntry(controlMain.model);
                xppe.setup(null, CurrentPart.Id, strXPath, prefixMappings, false); // Don't setup Q until after drop
                xppe.save();

                // Write tag
                td.set("od:xpath", xppe.xpathId);

                // Does this node contain XHTML?
                // TODO: error handling
                log.Info(nodeContent);

                if (isFlatOPC)
                {
                    // <?mso-application progid="Word.Document"?>
                    // <pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">

                    td.set("od:progid", "Word.Document");
                    title = "Word: " + xppe.xpathId;
                    needBind = false; // make it a rich text control

                }
                else if (isXHTML)
                {

                    td.set("od:ContentType", "application/xhtml+xml");
                    // TODO since this is a run-level sdt,
                    // the XHTML content will need to be run-level.
                    // Help the user with this?
                    // Or in a run-level context, docx4j could convert
                    // p to soft-enter?  But what to do about tables?
                    title = "XHTML: " + xppe.xpathId;

                    needBind = false; // make it a rich text control

                    // Word will only replace our HTML-imported-to-docx with the raw HTML
                    // if we have the bind.
                    // Without this, giving the user visual feedback in Word is a TODO
                }
                else if (isPicture)
                {
                    designMode.Off();
                    log.Debug("NEW Special case handling for pictures..");

                    //object missing = System.Type.Missing;
                    Globals.ThisAddIn.Application.Selection.Collapse(ref missing);
                    // Are they dragging to an existing picture content control
                    Word.ContentControl picCC = ContentControlMaker.getActiveContentControl(CurrentDocument, Globals.ThisAddIn.Application.Selection);
                    try
                    {
                        if (picCC == null
                            || (picCC.Type != Word.WdContentControlType.wdContentControlPicture))
                        {
                            picCC = CurrentDocument.ContentControls.Add(
                                Word.WdContentControlType.wdContentControlRichText, ref missing);
                            designMode.restoreState();
                        }
                    }
                    catch (COMException ce)
                    {
                        // Will happen if you try to drag a text node onto an existing image content control
                        log.Debug("Ignoring " + ce.Message);
                        return;
                    }
                    PictureUtils.setPictureHandler(td);
                    picCC.Title = "Image: " + xppe.xpathId;

                    picCC.Tag = td.asQueryString();

                    PictureUtils.pastePictureIntoCC(picCC,
                        Convert.FromBase64String(nodeContent));

                    return;

                }
                else
                {
                    title = "Data value: " + xppe.xpathId;
                    needBind = true;
                }
                tag = td.asQueryString();

            }
            else if (controlMain.controlMode1.isModeCondition())
            {
                log.Debug("In condition mode");
                ConditionsPartEntry cpe = new ConditionsPartEntry(controlMain.model);
                cpe.setup(CurrentPart.Id, strXPath, prefixMappings, false);
                cpe.save();

                title = "Conditional: " + cpe.conditionId;
                // Write tag
                td.set("od:condition", cpe.conditionId);
                tag = td.asQueryString();
            }
            else if (controlMain.controlMode1.isModeRepeat())
            {
                log.Debug("In repeat mode");

                // Need to drop eg [1] (if any), so BetterForm-based interactive processing works
                if (strXPath.EndsWith("]"))
                {
                    strXPath = strXPath.Substring(0, strXPath.LastIndexOf("["));
                    log.Debug("Having dropped '[]': " + strXPath);
                }

                XPathsPartEntry xppe = new XPathsPartEntry(controlMain.model);
                xppe.setup("rpt", CurrentPart.Id, strXPath, prefixMappings, false);
                xppe.save();

                title = "Data value: " + xppe.xpathId;
                // Write tag
                td.set("od:repeat", xppe.xpathId);
                tag = td.asQueryString();
            }

            //create the HTML
            string strHTML = string.Empty;
            if (isFlatOPC)
            {
                // <?mso-application progid="Word.Document"?>
                // <pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">
                nodeContent = ControlTreeView.EscapeXHTML(nodeContent);

                strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, Utilities.GetPrefixMappings(xmlnsMgr), CurrentPart.Id,
                    Utilities.MappingType.RichText, title, tag, nodeContent);

            }
            else if (isXHTML)
            {
                // need to escape eg <span> for it to get through the Clipboard
                nodeContent = ControlTreeView.EscapeXHTML(nodeContent);

                // use a RichText control, and set nodeContent
                strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, Utilities.GetPrefixMappings(xmlnsMgr), CurrentPart.Id,
                    Utilities.MappingType.RichText, title, tag, nodeContent);
                // alternatively, this could be done in DocumentEvents.doc_ContentControlAfterAdd
                // but to do it there, we'd need to manually resolve the XPath to
                // find the value of the CustomXMLNode it pointed to.

            }
            else if (!needBind)
            {
                // For conditions & repeats, we use a RichText control
                strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, Utilities.GetPrefixMappings(xmlnsMgr), CurrentPart.Id,
                    Utilities.MappingType.RichText, title, tag);
            }
            else
            {
                // Normal bind

                if (OwnerDocument.Schemas.Count > 0)
                {
                    switch (Utilities.CheckNodeType((XmlNode)tn.Tag))
                    {
                        case Utilities.MappingType.Date:
                            strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, prefixMappings, CurrentPart.Id, Utilities.MappingType.Date, title, tag);
                            break;
                        case Utilities.MappingType.DropDown:
                            strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, prefixMappings, CurrentPart.Id, Utilities.MappingType.DropDown, title, tag);
                            break;
                        case Utilities.MappingType.Picture:
                            strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, prefixMappings, CurrentPart.Id, Utilities.MappingType.Picture, title, tag);
                            break;
                        default:
                            strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, prefixMappings, CurrentPart.Id, Utilities.MappingType.Text, title, tag);
                            break;
                    }
                }
                else
                {
                    //String val = ((XmlNode)tn.Tag).InnerText;
                    if (ContentDetection.IsBase64Encoded(val))
                    {
                        // Force picture content control
                        strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, Utilities.GetPrefixMappings(xmlnsMgr), CurrentPart.Id,
                            Utilities.MappingType.Picture, title, tag);
                    }
                    else
                    {
                        strHTML = ClipboardUtilities.GenerateClipboardHTML(needBind, strXPath, Utilities.GetPrefixMappings(xmlnsMgr), CurrentPart.Id,
                            Utilities.MappingType.Text, title, tag);
                    }
                }
            }

            // All cases:-

            //notify ourselves of a pending drag/drop
            controlMain.NotifyDragDrop(true);

            //throw it on the clipboard to drag
            DataObject dobj = new DataObject();
            dobj.SetData(DataFormats.Html, strHTML);
            dobj.SetData(DataFormats.Text, tn.Text);
            controlTreeView.DoDragDrop(dobj, DragDropEffects.Move);

            //notify ourselves of a completed drag/drop
            controlMain.NotifyDragDrop(false);

            Clipboard.SetData(DataFormats.Text, ((XmlNode)tn.Tag).InnerXml);
        }