2016-01-17 2 views
2

Я пытаюсь создать пользовательскую библиотеку элементов управления. Сначала я подумал, что у меня закончена форма и полностью работает, но я этого не сделал. Вместо того, чтобы спрашивать, как исправить мою проблему с формой, я попрошу ее с помощью моей кнопки.Вложенные объекты wont "Stay"

Я создаю пользовательскую кнопку, которая широко настраивается с каждым состоянием, когда она может устанавливать каждый цвет, а также текст.

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

Сначала я покажу вам код, а затем объясню.

namespace OurCSharp.OurControls.Core.Buttons.Button 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.ComponentModel; 
    using System.Diagnostics; 
    using System.Drawing; 
    using System.Linq; 
    using System.Windows.Forms; 

    using OurCSharp.OurControls.Core.Buttons.Button.Properties; 
    using OurCSharp.OurControls.Core.Buttons.Enums; 
    using OurCSharp.OurControls.Core.Buttons.Interfaces; 

    [DefaultEvent("Click")] 
    public class OurButton : Control////, IOurButtonRoot 
    { 
     private Color _borderColor = Color.FromArgb(255, 25, 25, 25); 
     private Color _textColor = Color.FromArgb(255, 150, 150, 150); 

     // TODO We will see if this is actually ignored or not; it may be though because it is its default value. 
     private SizeF _textSizeF = SizeF.Empty; 

     private IOurButtonDesigner _buttonDesigner; 



     /// <summary> 
     /// The designers for each state of the button. 
     /// </summary> 
     [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] 
     public OurButtonDesigner ButtonDesign { get; set; } 

     /// <summary> 
     /// Gets or sets the background color for the control. 
     /// </summary> 
     /// <returns> 
     /// A <see cref="T:System.Drawing.Color"/> that represents the background color of the control. The default is the value of the <see cref="P:System.Windows.Forms.Control.DefaultBackColor"/> property. 
     /// </returns> 
     /// <PermissionSet><IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/></PermissionSet> 
     [DefaultValue(typeof (Color), "255, 75, 75, 75")] 
     public override Color BackColor 
     { 
      get { return base.BackColor; } 
      set 
      { 
       base.BackColor = value; 
       this.Invalidate(); 
      } 
     } 

     /// <summary> 
     /// Gets or sets the foreground color of the control. 
     /// </summary> 
     /// <returns> 
     /// The foreground <see cref="T:System.Drawing.Color"/> of the control. The default is the value of the <see cref="P:System.Windows.Forms.Control.DefaultForeColor"/> property. 
     /// </returns> 
     /// <PermissionSet><IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/></PermissionSet> 
     [DefaultValue(typeof(Color), "255, 150, 150, 150")] 
     public override Color ForeColor 
     { 
      get { return base.ForeColor; } 
      set 
      { 
       base.ForeColor = value; 
       this.Invalidate(); 
      } 
     } 

     /// <summary> 
     /// Gets or sets a value indicating whether this control should redraw its surface using a secondary buffer to reduce or prevent flicker. 
     /// </summary> 
     /// <returns> 
     /// true if the surface of the control should be drawn using double buffering; otherwise, false. 
     /// </returns> 
     [DefaultValue(true)] 
     protected override bool DoubleBuffered { get { return base.DoubleBuffered; } set { } } 

     public OurButton() 
     { 
      // TODO Might have to add in property for this with a description 
      // TODO Gotta update the minimum size... 
      base.AutoSize = true; 

      base.DoubleBuffered = true; 

      this.Padding = new Padding(6, 2, 6, 2); 

      base.Text = @"OurButton"; 

      this.ButtonDesign = new OurButtonDesigner(this); 

      Debug.WriteLine(this.ButtonDesign.Clicked.Text); 



      Debug.WriteLine(3); 
      this.Margin = new Padding(3); 

      // TODO Need to re-calcualte size aswell with padding is changed. 
      // TODO Also need to re-calculate on when the font is changed. 




      base.TextChanged += (sender, args) => this.Invalidate(); 





      base.Text = @"OurButton"; 

      // TODO May not need this hear, might just be able to call it in the 'OnCreateControl' 
      this.Invalidate(); 
     } 

     public void UpdateSize() { this.Size = this.CalculateSize(); } 

     private SizeF MeassureString(string str) => this.CreateGraphics().MeasureString(str, this.Font); 

     /// <summary> 
     /// Raises the <see cref="M:System.Windows.Forms.Control.CreateControl"/> method. 
     /// </summary> 
     protected override void OnCreateControl() 
     { 
      Debug.WriteLine(1); 
      base.OnCreateControl(); 
      Debug.WriteLine(2); 

      this._buttonDesigner = this.Enabled ? this.ButtonDesign.Normal : this.ButtonDesign.Disabled; 

      base.BackColor = this._buttonDesigner.BackColor; 
      base.ForeColor = this._buttonDesigner.TextColor; 

      var stringToArea = new KeyValuePair<string, float>(string.Empty, 0F); 

      foreach (var str in new[] 
           { 
            this.ButtonDesign.Normal.Text, 
            this.ButtonDesign.Hovered.Text, 
            this.ButtonDesign.Clicked.Text, 
            this.ButtonDesign.Disabled.Text 
           }) 
      { 
       var area = 0F; 

       Debug.WriteLine(str); 



       // TODO This may not work. 
       if (stringToArea.Value >= (area = this.CalculateStringArea(str))) { continue; } 

       stringToArea = new KeyValuePair<string, float>(str, area); 
      } 

      this._textSizeF = this.MeassureString(stringToArea.Key); 

      this.Size = this.CalculateSize(); 
      this.Text = this._buttonDesigner.Text; 

      Debug.WriteLine("HERE"); 

      Debug.WriteLine("{0}, {1}, {2}", this.Text, stringToArea.Key, stringToArea.Value); 

      this.Invalidate(); 
     } 

     // Calculating the Area is beter than Parimeter because Parimeter could be used for something like a Polygon. 
     private float CalculateStringArea(string str) 
     { 
      var sizeF = this.MeassureString(str); 
      return sizeF.Width * sizeF.Height; 
     } 

     ////private Size CalculateSize() 
     //// => 
     ////  (this._textSizeF = 
     ////   new SizeF(this.ButtonDesign.Orientation == ButtonOrientation.Verticle 
     ////      ? new Size((int)this._textSizeF.Height + this.Padding.Bottom + this.Padding.Top, 
     ////         (int)this._textSizeF.Width + this.Padding.Left + this.Padding.Right) 
     ////      : new Size((int)this._textSizeF.Width + this.Padding.Left + this.Padding.Right, 
     ////         (int)this._textSizeF.Height + this.Padding.Bottom + this.Padding.Top))).ToSize 
     ////   (); 

     private Size CalculateSize() 
     => 
      (
      new SizeF(this.ButtonDesign.Orientation == ButtonOrientation.Verticle 
          ? new Size((int)this._textSizeF.Height + this.Padding.Bottom + this.Padding.Top, 
             (int)this._textSizeF.Width + this.Padding.Left + this.Padding.Right) 
          : new Size((int)this._textSizeF.Width + this.Padding.Left + this.Padding.Right, 
             (int)this._textSizeF.Height + this.Padding.Bottom + this.Padding.Top))).ToSize 
       (); 

     /// <summary> 
     /// Raises the <see cref="E:System.Windows.Forms.Control.MouseClick"/> event. 
     /// </summary> 
     /// <param name="e">An <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data. </param> 
     protected override void OnMouseClick(MouseEventArgs e) 
     { 
      base.OnMouseClick(e); 

      // TODO Using a trenary may use more resources as it's always going to update the UI even if it's already disabled.. 
      /* 
      * Need re-assign text before the 'BackColor' and 'ForeColor' because once those are called, 
      * the button is going to set invalidated. 
      */ 
      this.Text = 
       (this._buttonDesigner = this.Enabled ? this.ButtonDesign.Clicked : this.ButtonDesign.Disabled).Text; 
      this.BackColor = this._buttonDesigner.BackColor; 
      this.ForeColor = this._buttonDesigner.TextColor; 

      // TODO May have to set the state back to something different after being clicked 
     } 

     /// <summary> 
     /// Raises the <see cref="E:System.Windows.Forms.Control.MouseEnter"/> event. 
     /// </summary> 
     /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data. </param> 
     protected override void OnMouseEnter(EventArgs e) 
     { 
      base.OnMouseEnter(e); 

      // TODO Using a trenary may use more resources as it's always going to update the UI even if it's already disabled.. 
      /* 
      * Need re-assign text before the 'BackColor' and 'ForeColor' because once those are called, 
      * the button is going to set invalidated. 
      */ 
      this.Text = 
       (this._buttonDesigner = this.Enabled ? this.ButtonDesign.Hovered : this.ButtonDesign.Disabled).Text; 
      this.BackColor = this._buttonDesigner.BackColor; 
      this.ForeColor = this._buttonDesigner.TextColor; 
     } 

     /// <summary> 
     /// Raises the <see cref="E:System.Windows.Forms.Control.MouseLeave"/> event. 
     /// </summary> 
     /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data. </param> 
     protected override void OnMouseLeave(EventArgs e) 
     { 
      base.OnMouseLeave(e); 

      // TODO Using a trenary may use more resources as it's always going to update the UI even if it's already disabled.. 
      /* 
      * Need re-assign text before the 'BackColor' and 'ForeColor' because once those are called, 
      * the button is going to set invalidated. 
      */ 
      this.Text = 
       (this._buttonDesigner = this.Enabled ? this.ButtonDesign.Normal : this.ButtonDesign.Disabled).Text; 
      this.BackColor = this._buttonDesigner.BackColor; 
      this.ForeColor = this._buttonDesigner.TextColor; 
     } 

     /// <summary> 
     /// Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event. 
     /// </summary> 
     /// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data. </param> 
     protected override void OnPaint(PaintEventArgs e) 
     { 
      base.OnPaint(e); 
      var g = e.Graphics; 
      var p = new Pen(this._borderColor); 

      var clientRect = this.ClientRectangle; 

      clientRect.Width--; 
      clientRect.Height--; 

      if (this._buttonDesigner.PaintBorder) 
      { 
       p.Color = this._buttonDesigner.BorderColor; 
       g.DrawRectangle(p, clientRect); 
      } 

      var b = new SolidBrush(this.ForeColor); 

      switch (this.ButtonDesign.Orientation) 
      { 
       case ButtonOrientation.Horizontal: 
        g.DrawString(this.Text, 
           this.Font, 
           b, 
           (int)this._textSizeF.Width/2F + this.Padding.Left, 
           this.Padding.Top, 
           new StringFormat() 
           { 
            Alignment = StringAlignment.Center 
           }); 
        break; 
       case ButtonOrientation.Verticle: 
        g.DrawString(this.Text, 
           this.Font, 
           b, 
           this.Padding.Top, 
           (int)this._textSizeF.Width/2F + this.Padding.Left, 
           new StringFormat() 
           { 

            FormatFlags = StringFormatFlags.DirectionVertical, 
            LineAlignment = StringAlignment.Center 
           }); 
        break; 
       default: 
        throw new ArgumentOutOfRangeException(); 
      } 

      ////g.DrawString(this.Text, 
      ////    this.Font, 
      ////    b, 
      ////    3, 
      ////    this.Padding.Top, ////this._textSizeF.Height/2F + 3F, 
      ////    this.ButtonDesign.Orientation == ButtonOrientation.Verticle 
      ////     ? new StringFormat 
      ////     { 
      ////      Alignment = StringAlignment.Center, 
      ////      FormatFlags = StringFormatFlags.DirectionVertical 
      ////     } 
      ////     : new StringFormat 
      ////     { 
      ////      Alignment = StringAlignment.Center 
      ////     }); 
     } 
    } 
} 

Здесь ButtonBaseClass

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace OurCSharp.OurControls.Core.Buttons.Button.Properties 
{ 
    using System.ComponentModel; 

    using OurCSharp.OurControls.Core.Buttons.Button.Properties.SubProperties; 
    using OurCSharp.OurControls.Core.Buttons.Enums; 
    using OurCSharp.OurControls.Core.Buttons.Interfaces; 

    public class OurButtonDesigner : IOurButtonBase 
    { 
     private readonly OurButton _ourButton; 

     private ButtonOrientation _orientation = ButtonOrientation.Horizontal; 

     public OurButtonDesigner(OurButton ourButton) 
     { 
      this._ourButton = ourButton; 
      this.Normal = new OurButtonHovered(ourButton); 
      this.Hovered = new OurButtonHovered(ourButton); 
      this.Clicked = new OurButtonClicked(ourButton); 
      this.Disabled = new OurButtonDisabled(ourButton); 
     } 

     /// <summary> 
     /// The orientation of the button. 
     /// </summary> 
     [DefaultValueAttribute(typeof(ButtonOrientation), "Horizontal")] 
     public ButtonOrientation Orientation 
     { 
      get { return this._orientation; } 
      set 
      { 
       this._orientation = value; 
       this._ourButton.UpdateSize(); 
       this._ourButton.Invalidate(); 
      } 
     } 

     /// <summary> 
     /// Designer for the button when in the 'Normal' state. 
     /// </summary> 
     public IOurButtonDesigner Normal { get; } 

     /// <summary> 
     /// Designer for the button when in the 'Hovered' state. 
     /// </summary> 
     public IOurButtonDesigner Hovered { get; } 

     /// <summary> 
     /// Designer for the button when in the 'Clicked' state. 
     /// </summary> 
     public IOurButtonDesigner Clicked { get; } 

     /// <summary> 
     /// Designer for the button when in the 'Designer' state. 
     /// </summary> 
     public IOurButtonDesigner Disabled { get; } 
    } 
} 

я серьезно извиниться за то, как дрянной это выглядит, я обычно не мой код, как это. Это обычно очень аккуратно.

Назад к теме.

Позволяет сосредоточиться только на ориентации.

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

Свойство ориентации отображается в свойствах gird во время разработки, и если я его изменю, он обновит кнопку на форме, чтобы либо перейти по вертикали, либо по горизонтали. Значение по умолчанию - горизонтальное.

Теперь, когда я меняю его на вертикальный, он изменяется, как сказано ранее, но как только я запускаю код для его проверки, он возвращается к горизонтали по умолчанию.

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

Мне действительно нужна помощь, может кто-то мне помочь?

ответ

1

Вы должны сказать дизайнеру, чтобы установить свойство вложенного объекта:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
    public OurButtonDesigner ButtonDesign { get; set; } 
+0

Say У меня есть интерфейс, который имеет элементы, которые имеют другой интерфейс, если я ставлю атрибуты тех членов (Имея в виду они имеют интерфейс), например, тот, который вы мне продемонстрировали, если я реализую этот интерфейс, будут атрибуты, которые находятся на элементах _interface в реализованном интерфейсе_ (если это не получилось, как курсив, я приношу свои извинения, я все еще изучать, как использовать эту форму)? Также, скажем, у меня есть вложенное свойство, и это также вложенное свойство. Нужно ли также украшать каждый вложенный класс? Или просто самый лучший? – Anonrate

+0

Для интерфейса и типа времени выполнения я не уверен; эксперимент. (посмотрите в '.Designer.cs' или попробуйте применить' [Description] 'к обоим и посмотрите, какая из них используется, все атрибуты используются от одного и того же члена) – SLaks

+0

Вам необходимо применить это к каждому свойству, содержимое которого вы хотите сериализации. – SLaks

Смежные вопросы