Привязка Richtextbox wpf

void hex_binary(char * res){
char binary[16][5] = {"0000", "0001", "0010", "0011", "0100", "0101","0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110","1111"};
char digits [] = "0123456789abcdef";

const char input[] = "a9e6"; // input value
res[0] = '\0';
int p = 0;
int value =0;
    while(input[p])
    {
        const char *v = strchr(digits, tolower(input[p]));
        if(v[0]>96){
            value=v[0]-87;
        }
        else{
            value=v[0]-48;
        }
        if (v){
            strcat(res, binary[value]);
        }
        p++;
    }
    printf("Res:%s\n", res);
}
69
задан Alex Maker 5 December 2008 в 10:48
поделиться

4 ответа

Я могу дать Вам хорошо решение, и можно пойти с ним, но прежде чем я сделаю я собираюсь попытаться объяснить, почему Документ не DependencyProperty для начала.

В течение времени жизни управления RichTextBox, свойство Document обычно не изменяется. RichTextBox инициализируется с FlowDocument. Тот документ отображен, может быть отредактирован и искажен во многих отношениях, но базовое значение свойства Document остается что один экземпляр FlowDocument. Поэтому нет действительно никакой причины, это должно быть Свойство Зависимости, т.е., Связываемое. Если у Вас есть несколько местоположений, которые ссылаются на этот FlowDocument, Вам только нужна ссылка однажды. Так как это - тот же экземпляр везде, изменения будут доступны для всех.

я не думаю, что FlowDocument поддерживает уведомления об изменении документа, хотя я не уверен.

Однако вот решение. Перед запуском так как RichTextBox не реализует INotifyPropertyChanged, и Документ не является свойством зависимости, у нас нет уведомлений, когда свойство RichTextBox's Document изменяется, таким образом, привязкой может только быть OneWay.

Создают класс, который обеспечит FlowDocument. Привязка требует существования Свойства Зависимости, таким образом, этот класс наследовался DependencyObject.

class HasDocument : DependencyObject
    {
        public static readonly DependencyProperty DocumentProperty =
            DependencyProperty.Register("Document", 
                                        typeof(FlowDocument), 
                                        typeof(HasDocument), 
                                        new PropertyMetadata(new PropertyChangedCallback(DocumentChanged)));

        private static void DocumentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            Debug.WriteLine("Document has changed");
        }

        public FlowDocument Document
        {
            get { return GetValue(DocumentProperty) as FlowDocument; }
            set { SetValue(DocumentProperty, value); }
        }
    }

Создают Окно с форматируемым полем в XAML.

<Window x:Class="samples.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Flow Document Binding" Height="300" Width="300"
    >
    <Grid>
      <RichTextBox Name="richTextBox" />
    </Grid>
</Window>

Дают Окну поле типа HasDocument.

HasDocument hasDocument;

конструктор Окна должен создать привязку.

hasDocument = new HasDocument();

InitializeComponent();

Binding b = new Binding("Document");
b.Source = richTextBox;
b.Mode = BindingMode.OneWay;
BindingOperations.SetBinding(hasDocument, HasDocument.DocumentProperty, b);

, Если бы Вы хотите смочь объявить привязку в XAML, необходимо было бы заставить класс HasDocument произойти из FrameworkElement так, чтобы это могло быть вставлено в логическое дерево.

Теперь, если необходимо было изменить свойство Document на HasDocument, Документ форматируемого поля также изменится.

FlowDocument d = new FlowDocument();
Paragraph g = new Paragraph();
Run a = new Run();
a.Text = "I showed this using a binding";
g.Inlines.Add(a);
d.Blocks.Add(g);

hasDocument.Document = d;
16
ответ дан Szymon Rozga 7 November 2019 в 09:40
поделиться

Создайте UserControl, который имеет RichTextBox.. Теперь добавьте следующее свойство зависимости:

    public FlowDocument Document
    {
        get { return (FlowDocument)GetValue(DocumentProperty); }
        set { SetValue(DocumentProperty, value); }
    }

    public static readonly DependencyProperty DocumentProperty =
        DependencyProperty.Register("Document", typeof(FlowDocument), typeof(RichTextBoxControl), new PropertyMetadata(OnDocumentChanged));

    private static void OnDocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        RichTextBoxControl control = (RichTextBoxControl) d;
        if (e.NewValue == null)
            control.RTB.Document = new FlowDocument(); //Document is not amused by null :)

        control.RTB.Document = document;
    }

Это решение состоит, вероятно в том, что решение "прокси" Вы видели где-нибудь.. Однако.. RichTextBox просто не имеет Документа как DependencyProperty... Таким образом, необходимо сделать это в другом отношении...

HTH

8
ответ дан Arcturus 7 November 2019 в 09:40
поделиться

Есть способ намного проще!

Вы можете легко создать прикрепленное свойство DocumentXaml (или DocumentRTF ), которое позволит вам привязать документ RichTextBox. Он используется следующим образом, где Autobiography - строковое свойство в вашей модели данных:

<TextBox Text="{Binding FirstName}" />
<TextBox Text="{Binding LastName}" />
<RichTextBox local:RichTextBoxHelper.DocumentXaml="{Binding Autobiography}" />

Voila! Полностью привязываемые данные RichTextBox!

Реализация этого свойства довольно проста: когда свойство установлено, загрузите XAML (или RTF) в новый FlowDocument. При изменении FlowDocument обновите значение свойства.

Этот код должен помочь:

using System.IO;  
using System.Text;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Documents;  
public class RichTextBoxHelper : DependencyObject
{
  public static string GetDocumentXaml(DependencyObject obj) 
  {
    return (string)obj.GetValue(DocumentXamlProperty); 
  }
  public static void SetDocumentXaml(DependencyObject obj, string value) 
  {
    obj.SetValue(DocumentXamlProperty, value); 
  }
  public static readonly DependencyProperty DocumentXamlProperty = 
    DependencyProperty.RegisterAttached(
      "DocumentXaml",
      typeof(string),
      typeof(RichTextBoxHelper),
      new FrameworkPropertyMetadata
      {
        BindsTwoWayByDefault = true,
        PropertyChangedCallback = (obj, e) =>
        {
          var richTextBox = (RichTextBox)obj;

          // Parse the XAML to a document (or use XamlReader.Parse())
          var xaml = GetDocumentXaml(richTextBox);
          var doc = new FlowDocument();
          var range = new TextRange(doc.ContentStart, doc.ContentEnd);

          range.Load(new MemoryStream(Encoding.UTF8.GetBytes(xaml)), 
            DataFormats.Xaml);

          // Set the document
          richTextBox.Document = doc;

          // When the document changes update the source
          range.Changed += (obj2, e2) =>
          {
            if(richTextBox.Document==doc)
            {
              MemoryStream buffer = new MemoryStream();
              range.Save(buffer, DataFormats.Xaml);
              SetDocumentXaml(richTextBox, 
                Encoding.UTF8.GetString(buffer.ToArray()));
            }
          };
       }});
     }

Тот же код можно использовать для TextFormats.RTF или TextFormats.XamlPackage. Для XamlPackage у вас будет свойство типа byte [] вместо строки.

Формат XamlPackage имеет несколько преимуществ по сравнению с обычным XAML, особенно возможность включать такие ресурсы, как изображения, и он более гибкий и простой в работе, чем RTF.

Трудно поверить, что этот вопрос длился 15 месяцев, и никто не указал на простой способ сделать это.

99
ответ дан 24 November 2019 в 13:18
поделиться

Я немного подправил предыдущий код. Прежде всего, range.Changed не работал у меня. После замены range.Changed на richTextBox.TextChanged оказалось, что обработчик события TextChanged может рекурсивно вызвать SetDocumentXaml, поэтому я сделал защиту от этого. Я также использовал XamlReader/XamlWriter вместо TextRange.

public class RichTextBoxHelper : DependencyObject
{
    private static HashSet<Thread> _recursionProtection = new HashSet<Thread>();

    public static string GetDocumentXaml(DependencyObject obj)
    {
        return (string)obj.GetValue(DocumentXamlProperty);
    }

    public static void SetDocumentXaml(DependencyObject obj, string value)
    {
        _recursionProtection.Add(Thread.CurrentThread);
        obj.SetValue(DocumentXamlProperty, value);
        _recursionProtection.Remove(Thread.CurrentThread);
    }

    public static readonly DependencyProperty DocumentXamlProperty = DependencyProperty.RegisterAttached(
        "DocumentXaml", 
        typeof(string), 
        typeof(RichTextBoxHelper), 
        new FrameworkPropertyMetadata(
            "", 
            FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
            (obj, e) => {
                if (_recursionProtection.Contains(Thread.CurrentThread))
                    return;

                var richTextBox = (RichTextBox)obj;

                // Parse the XAML to a document (or use XamlReader.Parse())

                try
                {
                    var stream = new MemoryStream(Encoding.UTF8.GetBytes(GetDocumentXaml(richTextBox)));
                    var doc = (FlowDocument)XamlReader.Load(stream);

                    // Set the document
                    richTextBox.Document = doc;
                }
                catch (Exception)
                {
                    richTextBox.Document = new FlowDocument();
                }

                // When the document changes update the source
                richTextBox.TextChanged += (obj2, e2) =>
                {
                    RichTextBox richTextBox2 = obj2 as RichTextBox;
                    if (richTextBox2 != null)
                    {
                        SetDocumentXaml(richTextBox, XamlWriter.Save(richTextBox2.Document));
                    }
                };
            }
        )
    );
}
15
ответ дан 24 November 2019 в 13:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: