Пользовательская метка не показывает текстовую строку - PullRequest
1 голос
/ 13 января 2012

Мне нужно было создать собственную метку для хранения некоторого значения, которое отличается от значения, отображаемого для пользователя

public class LabelBean : Label {
  private string value;

  public LabelBean(string text = "", string value = ""): base() {
    base.Text = text;
    this.value = value;
  }

  public string Value {
    get { return value; }
    set { this.value = value; }
  }
}

, но теперь в конструкторе формы я заменяю элемент управления своим классом

this.lbAttributeType = new LabelBean();

и позже после создания формы, но перед ее отображением я устанавливаю текст через setter

(this.lbAttributeType as LabelBean).Value = value;
this.lbAttributeType.Text = Transform(value);

, но в форме у меня всегда есть текст "label1" ... что такоене так с этим?спасибо

ОБНОВЛЕНИЕ

Я добавил решение, чтобы найти его проще:

public class MyLabel : Label {

    public MyLabel()
      : base() {
    }

    public string Value {
      set {
        this.Text = value;
      }
    }
  }

и форму с элементом управления Widnows.Forms.Label label1

public partial class Form1 : Form {

    public Form1() {
      InitializeComponent();
      this.Controls.Remove(this.label1);
      this.label1 = new MyLabel();
      this.Controls.Add(this.label1);
      (this.label1 as MyLabel).Value = "oh";
    }
  }

ошибка была в Controls.Remove и Controls.Add, спасибо всем за потраченное время:)

Ответы [ 3 ]

5 голосов
/ 13 января 2012

Полагаю, потому что, поскольку вы выполняете работу в конструкторе, код InitializeComponent, автоматически сгенерированный конструктором, перезаписывает экземпляр элемента управления, поскольку он, скорее всего, вызывается после вашей инициализации.

Если класс является частью проекта, вы найдете его на панели инструментов;это означает, что вы можете просто перетащить новый элемент управления в форму вместо существующего - это то, что вы должны сделать.

Это гарантирует, что сгенерированное конструктором свойство имеет тип LabelBean, ине просто Label.

Также - вы должны рассмотреть вопрос об изменении Value сеттера, как продемонстрировал WoLfulus (+1 там)

Обновление

В ответ на комментарийВы положили ответ WoLfulus - вот несколько альтернатив:

1) Если форма здесь является «умным» битом - рассмотрите возможность написания в ней вспомогательного метода и установки через него значения метки, используя свойство Tag:

public void SetLabelBean(Label target, string value)
{
  Label.Tag = value;
  Label.Text = Transform(value);
}

public string GetLabelBean(Label target)
{
  return target.Tag as string;
}

2) Продолжайте использовать свой подклассифицированный тип LabelBean (добавляя его через конструктор, как я уже упоминал) - но используйте абстракцию, чтобы дать емудоступ к методу Transform формы:

public interface ITransformProvider
{
  string Transform(string);
}

Заставьте ваш класс формы реализовать этот интерфейс с помощью метода Transform, к которому вы не обращаетесь.

Теперь в вашем классе LabelBean:

public ITransformProvider Transformer
{
  get{
    //searches up the control hierarchy to find the first ITransformProvider.
    //should be the form, but also allows you to use your own container controls
    //to change within the form.  The algorithm could be improved by caching the
    //result, invalidating it if the control is moved to another container of course.
    var parent = Parent;
    ITransformProvider provider = parent as ITransformProvider;
    while(provider == null){
      parent = parent.Parent;
      provider = parent as ITransformProvider;
    }
    return provider;
  }
}

иНаконец, используя немного измененный код WoLfulus, вы можете сделать это:

public string Value          
{         
  get          
  {          
    return value;          
  }         
  set          
  {          
    this.value = value; 
    var transformer = Transformer;
    if(transformer != null) this.Text = transformer.Transform(value);
  }         
}  

Это, я думаю, решит ваши проблемы с этим ответом.

5 голосов
/ 13 января 2012

Попробуйте это:

  1. Создание нового делегата вне класса метки:

    public delegate string LabelFormatDelegate( string val );
    
  2. Добавьте это к вашему классу этикетки:

    public LabelFormatDelegate ValueFormatter = null;
    
    public string Value 
    {
        get 
        { 
            return value; 
        }
        set 
        { 
            this.value = value; 
            if (this.ValueFormatter != null)
            {
                this.Text = this.ValueFormatter(value); // change the label here
            }
            else
            {
                this.Text = value;
            }
        }
    }
    
  3. Поместите новый общий ярлык в вашу форму (назовите его "label1")

  4. Перейдите к Form1.Designer.cs и найдите объявление "label1".

  5. Переименуйте тип «Метка» в свой собственный тип метки (например: «MyLabel»)

  6. Измените код инициализации метки на Функция InitializeComponent в коде конструктора для соответствия новому типу "MyLabel"

    Пример: * * тысяча тридцать-один

    this.label1 = new Label();
    

    Изменить на:

    this.label1 = new MyLabel();
    
  7. В событии Form_Load укажите функцию форматирования:

    this.label1.ValueFormatter = new LabelFormatDelegate(this.Transform);
    

Примечания: здесь вам тоже нужно убрать вызов установщика «Текст»:

(this.lbAttributeType as LabelBean).Value = value;
// this.lbAttributeType.Text = Transform(value);

Это будет синхронизировать ваше значение / текст, но не забудьте вручную установить свойство «Текст».

2 голосов
/ 13 января 2012

Я согласен с WoLfulus и Andreas Zoltan и добавил бы симметричную функциональность в Text, если существует однозначное обратное преобразование:

public string Value
{
    get { return value; }
    set
    {
        if (this.value != value) {
            this.value = value;
            this.Text = Transform(value);
        }
    }
}

public override string Text
{
    get { return base.Text; }
    set
    {
        if (base.Text != value) {
            base.Text = value;
            this.value = TransformBack(value);
        }
    }
}

Обратите внимание на проверки if, чтобы избежать бесконечной рекурсии.


EDIT:

Назначение вашей метки на lbAttributeType недостаточно. Вы должны удалить старую метку из коллекции Controls до назначения и повторно добавить ее после назначения.

this.Controls.Remove(lbAttributeType);  // Remove old label
this.lbAttributeType = new LabelBean(); 
this.Controls.Add(lbAttributeType); // Add new label

Ваша форма все еще отображала старый ярлык! Почему я раньше этого не видел?

...