so I managed to build my own simple user control. Basically it is a custom Button containing a child Label control on top of it. The button works as how it should be during runtime.
However during design time I got an issue whenever I cut-and-paste that button (let's say I want to move it from Panel1 to Panel2 by cut-and-paste).
The button itself retains its properties such as background color, etc, but the child Label inside it is reinitialized everytime we paste it, so the text and color inside that label changed back to its default value.
The value of the labels text is set by "Text" property which overrides Text property of the UserControl such as follows :
private String _text = "Button";
[Browsable(true), Description("Sets the text displayed on the button"), Category("Display Settings")]
public override String Text {
get => _text;
set {
_text = value;
lb_Text.Text = _text;
}
}
Is there a way to retain child control properties during cut-and-paste in the Designer view?
Below is the code generated for InitializeComponent() section of the UserControl, which will be called whenever it is added to a form. Details aside, I acknowledged that default text and color values is re-initialized there, so I'm not sure how we replace those during cut-and-paste.
private void InitializeComponent()
{
this.lb_Text = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// lb_Text
//
this.lb_Text.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(127)))), ((int)(((byte)(127)))), ((int)(((byte)(127)))), ((int)(((byte)(127)))));
this.lb_Text.Dock = System.Windows.Forms.DockStyle.Fill;
this.lb_Text.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Bold);
this.lb_Text.ForeColor = System.Drawing.Color.Black;
this.lb_Text.Location = new System.Drawing.Point(0, 0);
this.lb_Text.Name = "lb_Text";
this.lb_Text.Size = new System.Drawing.Size(200, 50);
this.lb_Text.TabIndex = 1;
this.lb_Text.Text = "Button";
this.lb_Text.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// MomentaryButton
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackgroundImage = global::HMIControls.Properties.Resources.Button_Normal;
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.Controls.Add(this.lb_Text);
this.Name = "MomentaryButton";
this.Size = new System.Drawing.Size(200, 50);
this.ResumeLayout(false);
}
Related
I have a ImageList, with one item, in the TabControl:
private System.Windows.Forms.ImageList tabControlMain_ilMain;
this.TabControlMain.ImageList = this.tabControlMain_ilMain;
this.tabControlMain_ilMain.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("tabControlMain_ilMain.ImageStream")));
this.tabControlMain_ilMain.TransparentColor = System.Drawing.Color.Silver;
this.tabControlMain_ilMain.Images.SetKeyName(0, "");
and I am setting this image to a specific TabPage:
this.tabControlMain_tp17.ImageIndex = 0;
and I can see in the designer the image attached to the TabPage, but when I am running the application, I cannot see the image, it is just an empty space near the TabPage name.
Does anyone know what could be the problem ?
Thank you!
P.S. What I have seen is that, if I am not selecting the ImageIndex, the TabPage header is getting less length, so I guess the image is taking the space, but cannot see it at runtime.
So i did nothing different than you i think. But mine is working.
Maybe remove and readd the controls.
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.TabControlMain = new System.Windows.Forms.TabControl();
this.tabControlMain_tp17 = new System.Windows.Forms.TabPage();
this.tabControlMain_ilMain = new System.Windows.Forms.ImageList(this.components);
this.TabControlMain.SuspendLayout();
this.SuspendLayout();
//
// TabControlMain
//
this.TabControlMain.Controls.Add(this.tabControlMain_tp17);
this.TabControlMain.ImageList = this.tabControlMain_ilMain;
this.TabControlMain.Location = new System.Drawing.Point(44, 42);
this.TabControlMain.Size = new System.Drawing.Size(192, 191);
//
// tabControlMain_tp17
//
this.tabControlMain_tp17.ImageIndex = 0;
this.tabControlMain_tp17.Location = new System.Drawing.Point(4, 23);
this.tabControlMain_tp17.Text = "tabControlMain_tp17";
//
// tabControlMain_ilMain
//
this.tabControlMain_ilMain.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("tabControlMain_ilMain.ImageStream")));
this.tabControlMain_ilMain.TransparentColor = System.Drawing.Color.Transparent;
this.tabControlMain_ilMain.Images.SetKeyName(0, "");
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 261);
this.Controls.Add(this.TabControlMain);
this.TabControlMain.ResumeLayout(false);
this.ResumeLayout(false);
}
private System.Windows.Forms.TabControl TabControlMain;
private System.Windows.Forms.TabPage tabControlMain_tp17;
private System.Windows.Forms.ImageList tabControlMain_ilMain;
All I need is a field that can be renamed by users as they wish by just clicking on it, I am using a label as the control here, when ever user click on it user could be able to enter text in the label and when he click outside of the label that enter text would be saved as the label text.
This is a quick solution:
private void label1_Click(object sender, EventArgs e)
{
TextBox tb = null;
if (label1.Controls.Count > 0) // do we already have created our TextBox?
{
tb = ((TextBox)label1.Controls[0]); // yes. set reference.
// is it already visible? we got clicked from outside, so we hide it:
if (tb.Visible) { label1.Text = tb.Text; tb.Hide(); return; };
}
else if (sender == null) return; // clicked from outside: do nothing
else // we need to create the textbox
{
tb = new TextBox();
tb.Parent = label1; // add it to the label's Controls collection
tb.Size = label1.Size; // size it
// set the event that ends editing when focus goes elsewhere:
tb.LostFocus += (ss, ee) => { label1.Text = tb.Text; tb.Hide(); };
}
tb.Text = label1.Text; // get current text
tb.Show(); // display the textbox in place
}
It embeds a TextBox into the Label. Style the Label to be big enough for the expected user entry!
It expects no other controls to be embedded there.
If you need it more than once consider creating a custom editable label from this code!
Note that to work you need to click at a spot where focus can go, not just the empty space around. To remedy that you could code the Click event for the surrounding space, maybe like this:
private void unClickLabel(object sender, EventArgs e) {label1_Click(null, null);}
In the form constructor add this to all the 'outside' controls that won't take focus, like the Form or a TabPage or a PicureBox or a Panel:
public Form1()
{
InitializeComponent();
this.Click += unClickLabel;
tabPage1.Click += unClickLabel;
pictureBox1.Click += unClickLabel;
..
}
Note that the new Label text will not persist program runs! To allow that you need to store it in some outside user settings and load them at startup..
You should create your own UserControl which contains one label and one textbox. Implement its functionality like you want.
I have created a sample usercontrol to give you an idea about it...
Update:
Follow these steps to use this custom control.
Right click on your project and click 'Add-> UserControl'
Name it 'EditableLabelControl' and click Add.
Go to 'EditableLabelControl.Designer.cs' and replace the partial class Code1 below.
Then go to 'EditableLabelControl.cs' and replace second partial class by Code2 below.
Build your solution.
You should be able to add EditableLabelControl to your form(it will be shown in toolbox)
Code1
partial class EditableLabelControl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(0, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(35, 13);
this.label1.TabIndex = 0;
this.label1.Text = "label1";
this.label1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.label1_MouseClick);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(0, 0);
this.textBox1.Name = "textBox1";
this.textBox1.TabIndex = 1;
this.textBox1.Visible = false;
this.textBox1.Leave += new System.EventHandler(this.textBox1_Leave);
//
// EditableLabelControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.Controls.Add(this.textBox1);
this.Controls.Add(this.label1);
this.Name = "EditableLabelControl";
this.Size = new System.Drawing.Size(103, 23);
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox1;
#endregion
}
Code2
public partial class EditableLabelControl : UserControl
{
public EditableLabelControl()
{
InitializeComponent();
}
private void label1_MouseClick(object sender, MouseEventArgs e)
{
textBox1.Visible = true;
textBox1.BringToFront();
textBox1.Focus();
}
private void textBox1_Leave(object sender, EventArgs e)
{
label1.Text = textBox1.Text;
textBox1.Visible = false;
textBox1.SendToBack();
}
}
Just add this EditableLabelControl to your form and it should work.
Try using TextBox instead of Label.
Use a TextBox control and set the ReadOnly property to true, if you would like to have a non-changeable text field. However, keep in mind, the TextBox will not resize automatically and does not support transparency.
You can change the property BackColor to Control and the BorderStyle to none, this will appear like a label.
With more effort you can create a UserControl and switch between the Lable and TextBox.
I recommend using textBox instead.
Replace the label with textBox.
//Set properties. Make the textBox looks like label
yourTextBox.BackColor = SystemColors.Control;
yourTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
//Allow user to change text by double clicking it
yourTextBox.DoubleClick += new EventHandler(this.doubleClick);
//Do stuff when user double click it. Double click again to end editing.
public void doubleClick(object sender, EventArgs e)
{
TextBox temp = (TextBox)sender;
temp.ReadOnly = !temp.ReadOnly;
temp.DeselectAll();
if (temp.ReadOnly)
{
//Make the textbox lose focus
this.ActiveControl = null;
}
}
I am using a gridview in a C# windows application. One of the cells has a long string of text (see below) but whenever it is bound to the grid the cell gets cropped and the scrollbar does not get to end of the grid to display the full text. The scrollbar doesn't scroll smoothly when dragging with a mouse either.
I tried different combinations for RowSize and ColumnSize` modes, but with no luck.
void FillGrid()
{
DataTable tasktable = new DataTable();
tasktable.Columns.Add("Logged By", typeof(string));
tasktable.Columns.Add("Date", typeof(DateTime));
tasktable.Columns.Add("Notes", typeof(string));
DataRow dr1;
//for (int i = 0; i < 100; i++)
//{
dr1 = tasktable.NewRow();
dr1[0] = "Sunit Shah";
dr1[1] = System.DateTime.Now;
dr1[2] = "Test Note";
tasktable.Rows.Add(dr1);
//}
dr1 = tasktable.NewRow();
dr1[0] = "Sunit Shah";
dr1[1] = System.DateTime.Now;
dr1[2] = "Test Note";
dr1[2] = "Paul Pogba will have a medical at Manchester United on Monday after
Juventus granted permission for him to seal a potential world record
transfer.Juventus manager Massimo Allegri refused to be drawn further
on the transfer when he was asked about it in his post-match press
conference following a friendly against West Ham at the London Stadium,
but an official at the Italian club confirmed they had authorised the
midfielder to have United doctors assess him ahead of the move.
Allegri merely said: ‘I spoke about Pogba the day before, we have
just finished a match and I don’t know much more, we will see on Monday
if he is a still Juventus player.’";
tasktable.Rows.Add(dr1);
DataTable fillNotesGrid = new DataTable();
fillNotesGrid = (from row in tasktable.AsEnumerable()
orderby row.Field<DateTime>("Date") descending
select row).CopyToDataTable();
dgvSIDetailsNotes.DataSource = fillNotesGrid;
}
From what I can gather, it looks like your problem isn't that it's truncating the data, it's that it's snapping to cells when you scroll, so it's right at the top of every cell when you scroll. If it's it's too big for the space available, you'll only see as much of the top part of that row as you can fit. Basically, it behaves like Microsoft Excel.
I don't think there's a way to turn off this behaviour in the standard DataGridView control.
HOWEVER, as a workaround you can add your DataGridView to a System.Windows.Forms.Panel, and make the Panel do your scrolling for you!
Simply make the DataGridView a child of the Panel control, and set the Panel's AutoScroll property to true and the DataGridView's AutoSize property to true and that should do the trick.
EDIT
I have included some source code to try and make things clear.
This is source code from the form (with the body of FillGrid()) omitted as it's identical to the source code in your question).
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
dataGridView1.DefaultCellStyle.WrapMode = DataGridViewTriState.True; //I'm assuming this is already set in your own source code as the cell is wrapping its text in your screenshot.
panel1.AutoScroll = true;
dataGridView1.AutoSize = true;
FillGrid();
}
void FillGrid()
{
...
}
}
This is how the controls are created in Form1.Designer.cs:
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.Panel panel1;
This is the generated InitializeComponent() method in the Designer.
private void InitializeComponent()
{
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.panel1 = new System.Windows.Forms.Panel();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// dataGridView1
//
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Location = new System.Drawing.Point(3, 3);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(145, 122);
this.dataGridView1.TabIndex = 0;
//
// panel1
//
this.panel1.Controls.Add(this.dataGridView1);
this.panel1.Location = new System.Drawing.Point(12, 12);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(260, 126);
this.panel1.TabIndex = 1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 261);
this.Controls.Add(this.panel1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
This should be everything you need to replicate this solution in a test project.
If you're experiencing issues with this in your main project then you may have other code that is interfering.
i was looking for trick to get the form name when mouse is place on it. suppose i have one mdi form and many sdi form like form1,form2,form3 and all sdi form are opened. suppose i have one timer running on form1 and which will run periodically. i want to show the form name on form1's label from the timer tick event when mouse is positioned on any SDI form window.
this way i try to do it. here is the code
private void timer1_Tick(object sender, EventArgs e) {
var handle = WindowFromPoint(Cursor.Position);
if (handle != IntPtr.Zero) {
var ctl = Control.FromHandle(handle);
if (ctl != null) {
label1.Text = ctl.Name;
return;
}
}
label1.Text = "None";
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr WindowFromPoint(Point pos);
the above code run perfectly but there is some glitch. when i place my mouse on MDI form or on Form1 then form name is showing on form1 but when i place the mouse on Form2 or Form2 then their name is not showing. i am not being able to understand what is the problem in this code. please guide me to fix it.
Since you have the control, I think you just need to use the FindForm() function:
var ctl = Control.FromHandle(handle);
if (ctl != null) {
var form = ctrl.FindForm();
if (form != null) {
label1.Text = form.Name;
}
}
The reason Form2's name isn't showing up is that the instance of Form2 that you have created does not have a name. In order to demonstrate this, take a look at the following code block, situated in a Program.cs file:
MDIParent mdi = new MDIParent();
Form1 frm1 = new Form1();
frm1.MdiParent = mdi;
Form2 frm2 = new Form2();
frm2.MdiParent = mdi;
frm1.Show();
frm2.Show();
Application.Run(mdi);
If you add a breakpoint, you will see that Form2's name is blank. But wait, there's more!
If you add a control, any control, to Form 2, it will have a name when you create it. It looks like the naming system does not feel the need to assign the form control a name until multiple controls are present, which it does during its InitializeComponent call. You can take a look at this code. Here is the code generated for "Form3" with no controls:
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Text = "Form3";
}
And here is the same form after a label has been added:
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(13, 13);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(35, 13);
this.label1.TabIndex = 0;
this.label1.Text = "label1";
//
// Form3
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.label1);
this.Name = "Form3";
this.Text = "Form3";
this.ResumeLayout(false);
this.PerformLayout();
}
As you can see, a name is only assigned to the form if other controls are present. As for why this is the case, you would probably have to ask the person who wrote the auto-generation code for that answer.
Ok, this is bugging me, and I just can't figure out what is wrong...
I have made two forms. First form just has a simple button on it, which opens the other as a dialog like so:
using (Form2 f = new Form2())
{
if (f.ShowDialog() != DialogResult.OK)
MessageBox.Show("Not OK");
else
MessageBox.Show("OK");
}
The second, which is that Form2, has two buttons on it. All I have done is to set the forms AcceptButton to one, and CancelButton to the other. In my head this is all that should be needed to make this work. But when I run it, I click on the button which opens up Form2. I can now click on the one set as CancelButton, and I get the "Not OK" message box. But when I click on the one set as AcceptButton, nothing happens?
The InitializeComponent code of Form2 looks like this:
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(211, 13);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
//
// button2
//
this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.button2.Location = new System.Drawing.Point(130, 13);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 1;
this.button2.Text = "button2";
this.button2.UseVisualStyleBackColor = true;
//
// Form2
//
this.AcceptButton = this.button1;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.button2;
this.ClientSize = new System.Drawing.Size(298, 59);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Name = "Form2";
this.Text = "Form2";
this.Load += new System.EventHandler(this.Form2_Load);
this.ResumeLayout(false);
}
I have done nothing else than add those two buttons, and set the AcceptButton and CancelButton. Why doesn't it work?
Just setting the AcceptButton/CancelButton is not enough. This just tells which button should be invoked on Enter/Esc. You have to set the button's DialogResult property.
Try setting DialogResult on button1
this.button1.DialogResult = System.Windows.Forms.DialogResult.OK;
Definitely try the tutorial How to easily apply AcceptButton and CancelButton for custom dialog box in Winform.
I had an issue with the AcceptButton not working and while the DialogResult suggestion was part of the fix, I had 2 other things that needed to change:
My button was not visible - Intentionally because I wanted to stop the "ding" when a carriage return was "pressed" by scanning a barcode.
The container that the button was inside made a difference. I had to have it in the same container, in my case a Forms.Panel, as the textbox that was trying to access it. I'm not sure why this would make a difference, but it did.
I hope this helps someone.
You need to set the KeyPreview property of the form to True, the default value is False. Remember that if focus is set to any other button rather than the AcceptButton the Enter key will execute this button