This is a migrated thread and some comments may be shown as answers.

Can't insert InlineUIContainer into the right palce

5 Answers 236 Views
RichTextBox
This is a migrated thread and some comments may be shown as answers.
yi
Top achievements
Rank 1
yi asked on 14 Oct 2015, 05:52 AM

For now, RadRichTextBox does not support dragging or pasting files. So I override the dragevent.

public class UserFile
    {
        public string name;
        public string absoluteAddress;
        public string image;
    }
 
    public class DragableRichTextBox : RadRichTextBox
    {
        public static readonly DependencyProperty UserFilesProperty;
        static int dirCount;
        static DragableRichTextBox()
        {
            FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata(new List<UserFile>(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault);
            UserFilesProperty = DependencyProperty.Register("UserFiles", typeof(List<UserFile>), typeof(RadRichTextBox), metadata);
            dirCount = 0;
        }
 
 
        public List<UserFile> UserFiles
        {
            get
            {
                userFiles.Clear();
                XamlFormatProvider provider = new XamlFormatProvider();
                XmlDocument xmlDocument = new XmlDocument();
                string data = provider.Export(this.Document);
                xmlDocument.LoadXml(data);
                scanFileAndAddIamge(xmlDocument.FirstChild);
                SetValue(UserFilesProperty, userFiles);
                return (List<UserFile>)GetValue(UserFilesProperty);
            }
            set { SetValue(UserFilesProperty, value); }
        }
        List<UserFile> userFiles;
        public string SaveDirectory;
        public DragableRichTextBox()
        {
            this.AllowDrop = true;
            this.AddHandler(RichTextBox.DropEvent, new DragEventHandler(dropIn), true);
            this.AddHandler(RichTextBox.DragOverEvent, new DragEventHandler(dropOver), true);
            userFiles = new List<UserFile>();
            string basePath = @"C:\123\temp";
            checkPath(basePath);
            for (int i = dirCount; i < 1000; ++i)
            {
                if (checkPath(basePath + @"\" + i))
                {
                    SaveDirectory = basePath + @"\" + i;
                    dirCount = i;
                    break;
                }
            }
        }
 
        bool checkPath(string path)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
                return true;
            }
            else if(dirCount == 0)
            {
                Directory.Delete(path, true);
            }
            return false;
        }
 
        private void dropIn(object obj, DragEventArgs de)
        {
            if (de.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = (string[])de.Data.GetData(DataFormats.FileDrop);
 
                foreach (string file in files)
                {
                    UserFile f = new UserFile();
                    System.Windows.Controls.Image image = new System.Windows.Controls.Image();
                    image.Source = GetIcon(file);
                    image.Height = image.Source.Height;
                    image.Width = image.Source.Width;
 
                    PngBitmapEncoder pictureEncoder = new PngBitmapEncoder();
                    pictureEncoder.Frames.Add(BitmapFrame.Create((BitmapSource)image.Source));
                    FileStream fs = new FileStream(String.Format(SaveDirectory + "/{0}.png", userFiles.Count), FileMode.OpenOrCreate, FileAccess.Write);
                    pictureEncoder.Save(fs);
                    fs.Close();
 
                    string path = String.Format(SaveDirectory + "/{0}.png", userFiles.Count);
                    f.image = path;
                    Uri uri = new Uri(path);
                    BitmapImage image1 = new BitmapImage(uri);
                    image.Source = image1;
 
                    StackPanel stk = new StackPanel();
                    stk.Children.Add(image);
                    Telerik.Windows.Controls.Label l = new Telerik.Windows.Controls.Label();
                    for (int i = file.Length - 1; i >= 0; --i)
                    {
                        if (file[i] == '\\')
                        {
                            l.Content = file.Remove(0, i + 1);
                            break;
                        }
                    }
                    Telerik.Windows.Controls.Label l1 = new Telerik.Windows.Controls.Label();
                    l1.Content = file;
                    l1.Visibility = Visibility.Collapsed;
                    stk.Children.Add(l);
                    stk.Children.Add(l1);
                    f.name = l.Content.ToString();
                    f.absoluteAddress = l1.Content.ToString();
                    userFiles.Add(f);
                    Section section = new Section();
                    Paragraph paragraph = new Paragraph();
                    InlineUIContainer container = new InlineUIContainer();
                    container.UiElement = stk;
                    container.Height = 25 + image.Height;
                    double x = l.Content.ToString().Length;
                    container.Width = x * 6.5 > image.Width ? x * 6.5 : image.Width;
                    paragraph.Inlines.Add(container);
                    section.Blocks.Add(paragraph);
                    this.Document.Sections.Add(section);
 
                    RecreateUI();
                    container.Width = stk.ActualWidth;
                }
            }
            RecreateUI();
        }
 
        private void dropOver(object obj, DragEventArgs de)
        {
            if (de.Data.GetDataPresent(DataFormats.FileDrop))
            {
                de.Effects = DragDropEffects.Copy;
            }
            else if (de.Data.GetDataPresent(DataFormats.Text) | de.Data.GetDataPresent(DataFormats.Bitmap) | de.Data.GetDataPresent(DataFormats.CommaSeparatedValue) | de.Data.GetDataPresent(DataFormats.Dib) | de.Data.GetDataPresent(DataFormats.Dif) | de.Data.GetDataPresent(DataFormats.EnhancedMetafile) | de.Data.GetDataPresent(DataFormats.FileDrop))
            {
                de.Effects = DragDropEffects.Scroll;
            }
            else
            {
                de.Effects = DragDropEffects.None;
            }
        }
 
        private ImageSource GetIcon(string fileName)
        {
            Icon icon = System.Drawing.Icon.ExtractAssociatedIcon(fileName);
            return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
                        icon.Handle,
                        new Int32Rect(0, 0, icon.Width, icon.Height),
                        BitmapSizeOptions.FromEmptyOptions());
        }
 
        private void RecreateUI()
        {
            if (this.ActiveEditorPresenter != null)
            {
                this.ActiveEditorPresenter.RecreateUI();
                this.UpdateEditorLayout();
            }
        }
 
        private void scanFileAndAddIamge(XmlNode node)
        {
            if (node.ChildNodes.Count == 0)
                return;
            foreach (XmlNode xn in node.ChildNodes)
            {
                if (xn.Name == "av:StackPanel")
                {
                    UserFile f = new UserFile();
                    foreach (XmlNode xn1 in xn.ChildNodes)
                    {
 
                        if (xn1.Name == "Label")
                        {
                            foreach (XmlAttribute attribute in xn1.Attributes)
                            {
                                if (attribute.Name == "Visibility" && attribute.Value == "Collapsed")
                                {
                                    f.absoluteAddress = xn1.InnerText;
                                }
                            }
                            if (xn1.Attributes.Count == 0)
                                f.name = xn1.InnerText;
                        }
                        if (xn1.Name == "av:Image")
                        {
                            foreach (XmlAttribute attribute in xn1.Attributes)
                            {
                                if (attribute.Name == "Source")
                                {
                                    for (int i = attribute.Value.Length - 1; i >= 0; --i)
                                    {
                                        if (attribute.Value[i] == '/')
                                        {
                                            attribute.Value = attribute.Value.Remove(0, i);
                                            break;
                                        }
                                    }
                                    attribute.Value = SaveDirectory + "/" + attribute.Value;
                                    f.image = attribute.Value;
                                    int kk = 11;
                                    kk++;
                                    kk++;
                                }
                            }
                        }
                    }
                    userFiles.Add(f);
                }
                else
                {
                    scanFileAndAddIamge(xn);
                }
            }
        }
    }

 I can drag files now, but the files alway insert in the end of the RadDoucument. I don't know how to get the paragragh or section that my mosue point.

Please help me.

5 Answers, 1 is accepted

Sort by
0
Accepted
Tanya
Telerik team
answered on 16 Oct 2015, 12:12 PM
Hi Yi,

I could suggest you to use the API of RadDocumentEditor. Using this API, it is guaranteed that all important updates will be triggered and you can easily insert the elements at the current position of the caret. You could obtain the position of the mouse in the handler of the DropEvent of RadRichTextBox through the ActiveEditorPresenter class and then move the caret to exactly this position. The snippet below demonstrates how I modified the code from the dropIn() method according to the described approach:
DocumentPosition position = this.ActiveEditorPresenter.GetDocumentPositionFromViewPoint(Mouse.GetPosition((this.ActiveEditorPresenter as UIElement)));
this.Document.CaretPosition.MoveToPosition(position);
 
InlineUIContainer container = new InlineUIContainer();
container.UiElement = stk;
container.Height = 25 + image.Height;
double x = l.Content.ToString().Length;
container.Width = x * 6.5 > image.Width ? x * 6.5 : image.Width;
                
RadDocumentEditor editor = new RadDocumentEditor(this.Document);
editor.InsertInline(container);
RecreateUI();
container.Width = stk.ActualWidth;

Hope this helps.

Regards,
Tanya
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
yi
Top achievements
Rank 1
answered on 18 Oct 2015, 06:17 AM

Hi Tanya,

 

This is what exactly I looking for. Thank you very much.

 

Best regards.

Yi.

0
yi
Top achievements
Rank 1
answered on 18 Oct 2015, 07:27 AM

Hi Tanya,

 Here comes another question. The RecreateUI() do not work. I debugged the program. It actually changed the stk.ActualWidth to a value, not zero. And the container.Width changed too. But did not show on the UI.

Regards,

Yi

0
Tanya
Telerik team
answered on 21 Oct 2015, 04:33 PM
Hi Yi,

Changing the size of the container is not recommended after this container has been already inserted in the document. The InlineUIContainer elements cannot be resized, copied and moved by design. You could try to change the size before the InsertInline() method. I tried to remove the line of code, which sets the container's width to the width of the StackPanel and the result seems good to me.

The RecreateUI() method seems unnecessary because this functionality is responsibility of the layer, which calls the same methods. I tested the behavior after removing this method and the result seems as expected.

I'm sorry I missed these clarifications in my previous reply.

Have you checked the height of the container? From the attached  I could suggest that the height is smaller than needed.

However, I couldn't reproduce the behavior you are describing and if my suggestions are not helpful, please share more information about the exact scenario or steps to reproduce in order to test the issue on our end.

Regards,
Tanya
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
yi
Top achievements
Rank 1
answered on 22 Oct 2015, 02:39 AM

I have sovled the problem by setting the width before insert.

Here are the codes.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Xml;
using Telerik.Windows.Controls;
using Telerik.Windows.Documents;
using Telerik.Windows.Documents.FormatProviders.Xaml;
using Telerik.Windows.Documents.Model;
 
 
namespace InfraStructure.View
{
    /// <summary>
    /// 用户文件类
    /// </summary>
    public class UserFile : StackPanel
    {
        public string name { get; set; }
        public string absoluteAddress { get; set; }
        public string image { get; set; }
    }
 
    /// <summary>
    /// 自定义可拖拽文件RichTextBox
    /// </summary>
    public class DragableRichTextBox : RadRichTextBox
    {
        static int count = 0;
        static string basePath = @"C:\123\temp";
 
        static DragableRichTextBox()
        {
            try
            {
                if (count == 0)
                {
                    if (Directory.Exists(basePath))
                    {
                        Directory.Delete(basePath, true);
                    }
                }
                count++;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
 
        List<UserFile> userFiles;
        //图片临时存储文件夹
        string SaveDirectory;
        /// <summary>
        /// 获取RichTextBox中包含的文件信息,只读
        /// </summary>
        public List<UserFile> UserFiles
        {
            get
            {
                userFiles.Clear();
                XamlFormatProvider provider = new XamlFormatProvider();
                XmlDocument xmlDocument = new XmlDocument();
                string data = provider.Export(this.Document);
                xmlDocument.LoadXml(data);
                scanFileAndAddIamge(xmlDocument.FirstChild);
                return userFiles;
            }
        }
 
        ///构造函数
        //添加了拖拽事件
        //确定了存储文件临时地址
        ///
        public DragableRichTextBox()
        {
            this.AllowDrop = true;
            this.AddHandler(RichTextBox.DropEvent, new DragEventHandler(dropIn), true);
            this.AddHandler(RichTextBox.DragOverEvent, new DragEventHandler(dropOver), true);
            userFiles = new List<UserFile>();
 
 
            checkPath(basePath);
            for (int i = 0; i < 10000; ++i)
            {
                if (checkPath(basePath + @"\" + i))
                {
                    SaveDirectory = basePath + @"\" + i;
                    break;
                }
            }
        }
        /// <summary>
        /// 路径检查,不存在则创建路径,返回true,存在直接返回false
        /// </summary>
        /// <param name="path">路径</param>
        /// <returns>是否存在路径</returns>
        bool checkPath(string path)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
                return true;
            }
            return false;
        }
 
        private void dropIn(object obj, DragEventArgs de)
        {
            if (de.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = (string[])de.Data.GetData(DataFormats.FileDrop);
 
                foreach (string file in files)
                {
                    UserFile f = new UserFile();
 
                    //获取文件icon
                    System.Windows.Controls.Image image = new System.Windows.Controls.Image();
                    image.Source = GetIcon(file);
                    image.Height = image.Source.Height;
                    image.Width = image.Source.Width;
 
                    //保存图片
                    PngBitmapEncoder pictureEncoder = new PngBitmapEncoder();
                    pictureEncoder.Frames.Add(BitmapFrame.Create((BitmapSource)image.Source));
                    FileStream fs = new FileStream(String.Format(SaveDirectory + "/{0}.png", userFiles.Count), FileMode.OpenOrCreate, FileAccess.Write);
                    pictureEncoder.Save(fs);
                    fs.Close();
 
                    //将文件加读取至image
                    string path = String.Format(SaveDirectory + "/{0}.png", userFiles.Count);
                    f.image = path;
                    Uri uri = new Uri(path);
                    BitmapImage image1 = new BitmapImage(uri);
                    image.Source = image1;
 
                    //整体布局构造
 
                    f.Children.Add(image);
                    Telerik.Windows.Controls.Label l = new Telerik.Windows.Controls.Label();
                    for (int i = file.Length - 1; i >= 0; --i)
                    {
                        if (file[i] == '\\')
                        {
                            l.Content = file.Remove(0, i + 1);
                            break;
                        }
                    }
                    Telerik.Windows.Controls.Label l1 = new Telerik.Windows.Controls.Label();
                    l1.Content = file;
                    l1.Visibility = Visibility.Collapsed;
                    f.Children.Add(l);
                    f.Children.Add(l1);
                    f.absoluteAddress = (string)l1.Content;
                    f.name = (string)l.Content;
 
                    //userFiles.count用来确定图片名
                    userFiles.Add(f);
 
                    //将stackPanel放入InlineUIContainer,加载至界面
                    InlineUIContainer container = new InlineUIContainer();
                    container.UiElement = f;
                    container.Height = 18 + image.Height;
                    container.Width = MeasureTextWidth((string)l.Content, l.FontSize, l.FontFamily.ToString());
                    DocumentPosition position = this.ActiveEditorPresenter.GetDocumentPositionFromViewPoint(Mouse.GetPosition((this.ActiveEditorPresenter as UIElement)));
                    this.Document.CaretPosition.MoveToPosition(position);
 
                    //插入界面
                    RadDocumentEditor editor = new RadDocumentEditor(this.Document);
                    editor.InsertInline(container);
                }
            }
        }
 
        private void dropOver(object obj, DragEventArgs de)
        {
            if (de.Data.GetDataPresent(DataFormats.FileDrop))
            {
                de.Effects = DragDropEffects.Copy;
            }
            else if (de.Data.GetDataPresent(DataFormats.Text) | de.Data.GetDataPresent(DataFormats.Bitmap) | de.Data.GetDataPresent(DataFormats.CommaSeparatedValue) | de.Data.GetDataPresent(DataFormats.Dib) | de.Data.GetDataPresent(DataFormats.Dif) | de.Data.GetDataPresent(DataFormats.EnhancedMetafile) | de.Data.GetDataPresent(DataFormats.FileDrop))
            {
                de.Effects = DragDropEffects.Scroll;
            }
            else
            {
                de.Effects = DragDropEffects.None;
            }
        }
 
        /// <summary>
        /// 获取文件icon
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns>文件图标</returns>
        private ImageSource GetIcon(string fileName)
        {
            Icon icon = System.Drawing.Icon.ExtractAssociatedIcon(fileName);
            return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
                        icon.Handle,
                        new Int32Rect(0, 0, icon.Width, icon.Height),
                        BitmapSizeOptions.FromEmptyOptions());
        }
 
        private void scanFileAndAddIamge(XmlNode node)
        {
            if (node.ChildNodes.Count == 0)
                return;
            foreach (XmlNode xn in node.ChildNodes)
            {
                if (xn.Name == "wa:UserFile")
                {
                    UserFile f = new UserFile();
                    foreach (XmlAttribute attribute in xn.Attributes)
                    {
                        if (attribute.Name == "name")
                        {
                            f.name = attribute.Value;
                        }
                        else if (attribute.Name == "absoluteAddress")
                        {
                            f.absoluteAddress = attribute.Value;
                        }
                        else if (attribute.Name == "image")
                        {
                            f.image = attribute.Value;
                        }
                    }
                    userFiles.Add(f);
                }
                else
                {
                    scanFileAndAddIamge(xn);
                }
            }
        }
 
        private double MeasureTextWidth(string text, double fontSize, string fontFamily)
        {
            FormattedText formattedText = new FormattedText(
            text,
            System.Globalization.CultureInfo.InvariantCulture,
            FlowDirection.LeftToRight,
            new Typeface(fontFamily.ToString()),
            fontSize,
            System.Windows.Media.Brushes.Black
            );
            return formattedText.WidthIncludingTrailingWhitespace + 11;
        }
    }
}
 

 Thanks for your help! It means a lot to me.

Best Regards,

Yi.

 

 

 

 

Tags
RichTextBox
Asked by
yi
Top achievements
Rank 1
Answers by
Tanya
Telerik team
yi
Top achievements
Rank 1
Share this question
or