Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

RichTextBox неправильная работа Clear()

64K
20 февраля 2012 года
skotina
5 / / 12.08.2011
Используется .NET Framework 3.5
Создаем следующий WindowsFormsApplication:


Код:
// Program.cs
using System;
using System.Linq;
using System.Windows.Forms;


namespace Problem
{
    static class Program
    {      
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());


        }
    }
}



Код:
//InformationForm.cs
using System;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace Problem
{
     class InformationForm : Form
    {

        public InformationForm()
        {
            InitializeComponent();
        }

        public void Print(String msg)
        {
            // tbInfo1 is TextBox
            // tbInfo2 is RichTextBox


          //  tbInfo1.Text = ""; // [experiment 1]
             tbInfo1.Clear(); // or tbInfo1.Text = null; This is the same(checked in .net Reflector) [experiment 2]
            tbInfo1.AppendText(msg + Environment.NewLine);



            //tbInfo2.Text = ""; // [experiment 1]
            tbInfo2.Clear(); //or tbInfo2.Text = null; This is the same [experiment 2]
            tbInfo2.AppendText(msg + Environment.NewLine);




        }


        #region Visual Studio generated code
       
        private System.ComponentModel.IContainer components = null;        
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }          
        private void InitializeComponent()
        {          
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InformationForm));
            this.tbInfo1 = new System.Windows.Forms.TextBox();
            this.tbInfo2 = new System.Windows.Forms.RichTextBox();
            this.SuspendLayout();
            //
            // tbInfo1
            //
            this.tbInfo1.Location = new System.Drawing.Point(12, 12);
            this.tbInfo1.Multiline = true;
            this.tbInfo1.Name = "tbInfo1";
            this.tbInfo1.Size = new System.Drawing.Size(258, 134);
            this.tbInfo1.TabIndex = 0;
            //
            // tbInfo2
            //
            this.tbInfo2.Location = new System.Drawing.Point(16, 207);
            this.tbInfo2.Name = "tbInfo2";
            this.tbInfo2.Size = new System.Drawing.Size(253, 113);
            this.tbInfo2.TabIndex = 1;
            this.tbInfo2.Text = "";
            //
            // InformationForm
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;          
            this.ClientSize = new System.Drawing.Size(282, 338);
            this.Controls.Add(this.tbInfo2);
            this.Controls.Add(this.tbInfo1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "InformationForm";
            this.Text = "Info";
            this.ResumeLayout(false);
            this.PerformLayout();

        }    

        private System.Windows.Forms.TextBox tbInfo1;
        private System.Windows.Forms.RichTextBox tbInfo2;



        #endregion





    }
   
}


Код:
// Form1.cs
using System;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace Problem
{
    class Form1 : Form
    {
        private InformationForm IF;
        public Form1()
        {
            InitializeComponent();
            IF = new InformationForm();
        }
        private void btnStart_Click(object sender, EventArgs e)
        {

            IF.Print("Hello World!");
            IF.ShowDialog();
        }

        #region Visual Studio generated code
     
        private System.ComponentModel.IContainer components = null;        
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        private void InitializeComponent()
        {
            this.btnStart = new System.Windows.Forms.Button();
            this.SuspendLayout();
            //
            // btnStart
            //
           
            this.btnStart.Location = new System.Drawing.Point(133, 89);
            this.btnStart.Name = "btnStart";
            this.btnStart.Size = new System.Drawing.Size(77, 66);
            this.btnStart.TabIndex = 1;
            this.btnStart.Text = "Go";
            this.btnStart.UseVisualStyleBackColor = false;
            this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
            //
            // Form1
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;          
            this.ClientSize = new System.Drawing.Size(351, 269);
            this.Controls.Add(this.btnStart);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.Name = "Form1";        
            this.ResumeLayout(false);

        }    

        private System.Windows.Forms.Button btnStart;
        #endregion


    }
   
}

Эксперимент 1

1)Запускаем приложение, жмем кнопку Go,закрываем модальное окно, вновь жмем на Go, вновь закрываем модальное окно и так несколько раз.

2)Видим, что все работает так как надо, то есть при очередном вызове функции Print содержимое текстовых полей сначала очищается, потом добавляется новая строка.

Эксперимент 2

1)В функции Print комментируем эксперимент 1 и откомментируем эксперимент 2 ( с вызовом функции Clear() )

2)Запускаем приложение, жмем кнопку Go,закрываем модальное окно, вновь жмем на Go, вновь закрываем модальное окно и так несколько раз.

3)Видим, что в текстбоксе функция Clear() работает корректно, а в ричтекстбоксе нет, удаления не происходит.

Странное поведение, тем более, что и TextBox и RichTextBox используют метод родителя TextBoxBase, никак не переопределяя его.

На странице документации http://msdn.microsoft.com/ru-ru/library/system.windows.forms.textboxbase.clear.aspx ничего про такое различное поведение не сказано, более того "Этот метод можно использовать для очистки содержимого элемента управления, вместо присвоения свойству Text пустой строки." Все-таки выходит что эти две техники не эквивалентны.

Так все-таки это баг, допущенный разработчиками .net framework'a или фича, которую следует добавить в официальную документацию?
Или может быть что-то в коде неграмотно написано?
P.S. Извиняюсь за объем кода, изначально планировал обратиться к разработчикам самого framework'a с описанием ошибки, но к сожалению, сотрудник чата дважды отсылал меня по ложному пути.Попытки написать на форуме msdn также не увенчались успехом, так как будучи зареганым, мне каждый раз предлагали новую регистрацию, без возможности войти в акк :(
297
20 февраля 2012 года
koodeer
1.2K / / 02.05.2009
Угу, любопытно.

Если посмотреть код свойства Text обоих контролов, то видно различие, и становится ясно такое поведение RichTextBox. Там при установке Text задаются значение внутренних полей textRef и textPlain. А при получении свойства Text, если эти внутренние поля равны null, выдаётся значение base.Text. Ну и получается таким образом предыдущее значение. Я так понял при быстром изучении.

Считать это багом или фичей - затрудняюсь ответить.


Дополню.
Такое, казалось бы, нелогичное поведение РичТекстБокса основано на том, что он хранит внутри форматированный текст. При его создании, при первом вызове свойства Text делаются определённые инициализирующие операции. Поэтому просто задать null недостаточно, ведь нужно сохранить некое начальное значение форматирования.
Пожалуй, всё же разработчикам этого контрола следовало предусмотреть такой вариант событий.
64K
21 февраля 2012 года
skotina
5 / / 12.08.2011
Спасибо.Все-таки похоже на баг, так как использутеся приравнивание к null в методе Clear() - название говорит само за себя.Кстати, как я понял, выходит что при отображении текста на форму используется геттер свойства Text ?
Вновь откроем проект и попробуем его пройти шаг за шагом, используя F10 и F11 для захода в функцию Print() в Visual Studio
Выясняется что при "быстром" проходе, заходя в функцию Print(), работает также как и при Ctrl+F5, то есть без удаления.Но при "относительно медленном" проходе, то есть останавливаясь на строке tbInfo2.Clear(); и убеждаясь что контрол очищается работает так, как надо. Если взглянуть на код геттера,




Код:
[Localizable(true), RefreshProperties(RefreshProperties.All)]
public override string Text
{
    get
    {
        if (base.IsDisposed)
        {
            return base.Text;
        }
        if (base.RecreatingHandle || base.GetAnyDisposingInHierarchy())
        {
            return "";
        }
        if (!base.IsHandleCreated && (this.textRtf == null))
        {
            if (this.textPlain != null)
            {
                return this.textPlain;
            }
            return base.Text;
        }
        this.ForceHandleCreate();
        return this.StreamOut(0x11);
    }

   
}

то можно сделать вывод, что при быстром проходе не успевает создаться хэндл, то есть свойство base.IsHandleCreated == false, а при относительно медленном успевает создаться.Или проблема кроется в чем-то другом?(c хэндлами не особо знаком)


Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог