Created the following code to workout some bugs in a bigger program. That said, when I click the button to add a row, the next row is added, but the previously created ComboBox (cmboPhoneType) disappears with each new click. What am I missing how to correct? Does this maybe have something to do with the name of the control?
using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
namespace AddNewRowTest
{
public partial class Form1 : Form
{
int leftControl = 1;
ComboBox cmboPhoneType = new ComboBox();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
addLabels();
btn_AddRow.PerformClick();
}
private void btn_AddRow_Click(object sender, EventArgs e)
{
//Connection Information redacted
reConn.Open();
MySqlCommand phoneTypeCommand = new MySqlCommand("Select * from lutable_phonetype order by Type;", reConn);
MySqlDataAdapter phoneTypeAdapter = new MySqlDataAdapter();
DataTable phoneTypeTable = new DataTable();
phoneTypeAdapter.SelectCommand = phoneTypeCommand;
phoneTypeAdapter.Fill(phoneTypeTable);
this.Controls.Add(cmboPhoneType);
cmboPhoneType.Top = leftControl * 36;
cmboPhoneType.Left = 12;
cmboPhoneType.Size = new Size(100, 20);
cmboPhoneType.DataSource = phoneTypeTable;
cmboPhoneType.DisplayMember = "Type";
cmboPhoneType.ValueMember = "TypeID";
cmboPhoneType.DataBindings.Add("SelectedValue", phoneTypeTable, "TypeID");
cmboPhoneType.SelectedIndexChanged += new System.EventHandler(cmboPhoneType_SelectedIndexChanged);
MaskedTextBox msktxtPhone = new MaskedTextBox();
this.Controls.Add(msktxtPhone);
msktxtPhone.Top = leftControl * 36;
msktxtPhone.Left = 116;
msktxtPhone.Size = new Size(100, 20);
msktxtPhone.Mask = "(999) 000-0000";
reConn.Close();
leftControl++;
}
private void addLabels()
{
Label lblPhoneType = new Label();
this.Controls.Add(lblPhoneType);
lblPhoneType.Top = leftControl * 12;
lblPhoneType.Left = 12;
lblPhoneType.Text = "Phone Type";
Label lblPhoneNumber = new Label();
this.Controls.Add(lblPhoneNumber);
lblPhoneNumber.Top = leftControl * 12;
lblPhoneNumber.Left = 116;
lblPhoneNumber.Text = "Phone Number";
}
private void cmboPhoneType_SelectedIndexChanged(object sender, EventArgs e)
{
cmboPhoneType.DataBindings.Clear();
}
}
}
Your Adding a "New" Masked Text Box in your Click Event but no "New" Combo Box. Then after you Declare a new cmbophonetype you will need to move, this.Controls.Add(cmboPhoneType); down, to just before you add the SelectedIndexChanged event handler. That will keep the Combobox visible but you may have some more problems separating all of the events.
I have an WinForms app built with vb .net to which I've added a WPF user control. The WPF user control consists of only a progressbar. I can drag the WPF control from the toolbax and add it to the Main Form in WinForms vb .net. But I don't know how to let my WinForms app dynamically set the value for the WPF progress bar. Anyway I can dynamically set the WPF control progress bar's value from my WinForms app?
Note: The reason Im using WPF progress bar instead of using WinForms progress bar is so that I can have blue colored progress bar in my WinForms app.
Since it may not be as straightforward as it may look like on paper, here's a custom ProgressBar that allows to set the Color of the bar and also change its style on the fly.
The ProgressBarStyle property sets the current style: the BarStyle.Standard style uses the ProgressBarRenderer.DrawHorizontalBar() method to draw its background, while the BarStyle.Flat selects the Parent.BackColor as background color and uses a fixed white border to draw the ProgressBar bounds and SystemColors.Highlight as the bar color. Of course it can be changed to support any other color and the Standard style.
The StringFormat class is used to center the text of the ProgressBar (in Standard style only. This can also be easily changed), setting both Horizontal and Vertical alignment to StringAlignment.Center.
The text color changes automatically to adapt to the Brightness of the ProgressBar color (it's just a simple adjustment, the HSL value on its own cannot always determine what text color better fits a background color).
Some magic values are just offsets used to adapt the drawing rectangles to the shapes designed by ProgressBarRenderer
This is how it works:
VB.Net version of the Custom Control:
Imports System.ComponentModel
Imports System.Drawing.Drawing2D
Imports System.Drawing
Imports System.Windows.Forms
<DesignerCategory("Code")>
Public Class ProgressBarCustomColor
Inherits ProgressBar
Private m_ParentBackColor As Color = SystemColors.Window
Private m_ProgressBarStyle As BarStyle = BarStyle.Standard
Private m_FlatBorderColor As Color = Color.White
Public Sub New()
SetStyle(ControlStyles.AllPaintingInWmPaint Or
ControlStyles.UserPaint Or
ControlStyles.OptimizedDoubleBuffer, True)
End Sub
Public Enum BarStyle
Standard
Flat
End Enum
Public Property ProgressBarStyle As BarStyle
Get
Return m_ProgressBarStyle
End Get
Set
m_ProgressBarStyle = Value
If DesignMode Then Me.Parent?.Refresh()
End Set
End Property
Public Property FlatBorderColor As Color
Get
Return m_FlatBorderColor
End Get
Set
m_FlatBorderColor = Value
If DesignMode Then Me.Parent?.Refresh()
End Set
End Property
Protected Overrides Sub OnParentChanged(e As EventArgs)
MyBase.OnParentChanged(e)
m_ParentBackColor = If(Me.Parent IsNot Nothing, Me.Parent.BackColor, SystemColors.Window)
End Sub
Protected Overrides Sub OnPaintBackground(e As PaintEventArgs)
MyBase.OnPaintBackground(e)
Dim rect = Me.ClientRectangle
If m_ProgressBarStyle = BarStyle.Standard Then
ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rect)
Dim baseColor = Color.FromArgb(240, Me.BackColor)
Dim highColor = Color.FromArgb(160, baseColor)
Using baseBrush = New SolidBrush(baseColor),
highBrush = New SolidBrush(highColor)
e.Graphics.FillRectangle(highBrush, 1, 2, rect.Width, 9)
e.Graphics.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1)
End Using
Else
Using pen = New Pen(m_FlatBorderColor, 2),
baseBrush = New SolidBrush(m_ParentBackColor)
e.Graphics.FillRectangle(baseBrush, 0, 0, rect.Width - 1, rect.Height - 1)
e.Graphics.DrawRectangle(pen, 1, 1, Me.ClientSize.Width - 2, Me.ClientSize.Height - 2)
End Using
End If
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Dim rect = New RectangleF(PointF.Empty, Me.ClientSize)
rect.Width = CType(rect.Width * (CType(Me.Value, Single) / Me.Maximum), Integer)
rect.Size = New SizeF(rect.Width - 2, rect.Height)
Dim hsl As Single = Me.ForeColor.GetBrightness()
If m_ProgressBarStyle = BarStyle.Standard Then DrawStandardBar(e.Graphics, rect, hsl)
If m_ProgressBarStyle = BarStyle.Flat Then DrawFlatBar(e.Graphics, rect, hsl)
End Sub
Private Sub DrawStandardBar(g As Graphics, rect As RectangleF, hsl As Single)
g.SmoothingMode = SmoothingMode.AntiAlias
g.CompositingQuality = CompositingQuality.HighQuality
Dim baseColor = Color.FromArgb(240, Me.ForeColor)
Dim highColor = Color.FromArgb(160, baseColor)
Using baseBrush = New SolidBrush(baseColor),
highBrush = New SolidBrush(highColor),
sf = New StringFormat(StringFormatFlags.MeasureTrailingSpaces)
sf.LineAlignment = StringAlignment.Center
sf.Alignment = StringAlignment.Center
g.FillRectangle(highBrush, 1, 2, rect.Width, 9)
g.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1)
g.DrawString($"{Me.Value} %", Me.Parent.Font,
If(hsl > 0.49F, Brushes.Black, Brushes.White), Me.ClientRectangle, sf)
End Using
End Sub
Private Sub DrawFlatBar(g As Graphics, rect As RectangleF, hsl As Single)
Using baseBrush = New SolidBrush(SystemColors.Highlight)
g.FillRectangle(baseBrush, 2, 2, rect.Width - 2, rect.Height - 4)
End Using
End Sub
End Class
C# version:
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
[DesignerCategory("Code")]
public class ProgressBarCustomColor : ProgressBar
{
private Color m_ParentBackColor = SystemColors.Window;
private Color m_FlatBorderColor = Color.White;
private BarStyle m_ProgressBarStyle = BarStyle.Standard;
public ProgressBarCustomColor()
{
this.SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.OptimizedDoubleBuffer, true);
}
public enum BarStyle { Standard, Flat }
public BarStyle ProgressBarStyle {
get => m_ProgressBarStyle;
set {
m_ProgressBarStyle = value;
if (DesignMode) this.Parent?.Refresh();
}
}
public Color FlatBorderColor {
get => m_FlatBorderColor;
set {
m_FlatBorderColor = value;
if (DesignMode) this.Parent?.Refresh();
}
}
protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
m_ParentBackColor = this.Parent?.BackColor ?? SystemColors.Window;
}
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
var rect = this.ClientRectangle;
if (m_ProgressBarStyle == BarStyle.Standard) {
ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rect);
var baseColor = Color.FromArgb(240, this.BackColor);
var highColor = Color.FromArgb(160, baseColor);
using (var baseBrush = new SolidBrush(baseColor))
using (var highBrush = new SolidBrush(highColor)) {
e.Graphics.FillRectangle(highBrush, 1, 2, rect.Width, 9);
e.Graphics.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1);
}
}
else {
using (var pen = new Pen(m_FlatBorderColor, 2))
using (var baseBrush = new SolidBrush(m_ParentBackColor)) {
e.Graphics.FillRectangle(baseBrush, 0, 0, rect.Width - 1, rect.Height - 1);
e.Graphics.DrawRectangle(pen, 1, 1, this.ClientSize.Width - 2, this.ClientSize.Height - 2);
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
var rect = new RectangleF(PointF.Empty, this.ClientSize);
rect.Width = (int)(rect.Width * ((float)this.Value / this.Maximum));
rect.Size = new SizeF(rect.Width - 2, rect.Height);
float hsl = this.ForeColor.GetBrightness();
if (m_ProgressBarStyle == BarStyle.Standard) DrawStandardBar(e.Graphics, rect, hsl);
if (m_ProgressBarStyle == BarStyle.Flat) DrawFlatBar(e.Graphics, rect, hsl);
}
private void DrawStandardBar(Graphics g, RectangleF rect, float hsl)
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.CompositingQuality = CompositingQuality.HighQuality;
var baseColor = Color.FromArgb(240, this.ForeColor);
var highColor = Color.FromArgb(160, baseColor);
using (var baseBrush = new SolidBrush(baseColor))
using (var highBrush = new SolidBrush(highColor))
using (var sf = new StringFormat(StringFormatFlags.MeasureTrailingSpaces)) {
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
g.FillRectangle(highBrush, 1, 2, rect.Width, 9);
g.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1);
g.DrawString($"{this.Value} %", this.Parent.Font,
hsl > .49f ? Brushes.Black : Brushes.White, this.ClientRectangle, sf);
}
}
private void DrawFlatBar(Graphics g, RectangleF rect, float hsl)
{
using (var baseBrush = new SolidBrush(SystemColors.Highlight)) {
g.FillRectangle(baseBrush, 2, 2, rect.Width - 2, rect.Height - 4);
}
}
}
So I want to pass data when I clicked an Canvas. So I have this code;
Canvas event_canvas = new Canvas();
event_canvas.Background = new SolidColorBrush(Color.FromRgb(66, 70, 77));
event_canvas.Width = 250;
event_canvas.Height = 60;
event_canvas.Margin = new Thickness(40, 0, 0, 0);
event_canvas.HorizontalAlignment = HorizontalAlignment.Left;
event_canvas.VerticalAlignment = VerticalAlignment.Top;
event_canvas.Cursor = Cursors.Hand;
#endregion
#region Grid (event_grid)
Grid event_grid = new Grid();
event_grid.Width = 250;
event_grid.Height = 60;
#endregion
#region TextBlock (event_text)
TextBlock event_text = new TextBlock();
event_text.VerticalAlignment = VerticalAlignment.Center;
event_text.HorizontalAlignment = HorizontalAlignment.Center;
event_text.Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255));
event_text.Text = e.name;
#endregion
event_grid.Children.Add(event_text); // Add the textblock to the grid
event_canvas.Children.Add(event_grid); // Add the grid to the canvas
grid_events.Children.Add(event_canvas); // Add the canvas to the main grid.
// Click event registration
event_canvas.MouseLeftButtonDown += Event_canvas_MouseLeftButtonDown;
And then in the trigger;
private void Event_canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Page pg = new EventDetailPage();
// Replaces all the content!!!!!
this.Content = pg;
//throw new NotImplementedException();
}
I tried to add this;
var param = ((TextBlock)sender).Text;
Page pg = new EventDetailPage(param);
But that code doesn't work, it throws an error that I can't get a value.
How can I fix this issue?
Cast the sender argument to Canvas and then access the Grid through the Canvas' Children collecton and the TextBlock through the Grid's Children collecton:
private void Event_canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Canvas canvas = (Canvas)sender;
Grid event_grid = canvas.Children[0] as Grid;
TextBlock event_text = event_grid.Children[0] as TextBlock;
string text = event_text.Text;
...
}
Using Windows Forms, two link labels are created dynamically. When the user clicks on anyone of links labels, one dynamic form is created. In that form I created one data grid, a text box and a button placed dynamically (in that dynamic form). Now I want to access the dynamic data grid in the dynamic button click event. How can I do that?
private void Users_Load(object sender, EventArgs e)
{
da = new SqlDataAdapter("Usp_Get_Employees", con);
ds = new DataSet();
da.Fill(ds);
if (ds.Tables[0].Rows.Count > 0)
{
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
string somecode = i.ToString() + ds.Tables[0].Rows[i]["eid"].ToString();
LinkLabel lbluser = new LinkLabel();
lbluser.Name = ds.Tables[0].Rows[i]["eid"].ToString();
lbluser.Text = ds.Tables[0].Rows[i]["ename"].ToString();
lbluser.Location = new System.Drawing.Point(40, i * 40);
lbluser.Size = new System.Drawing.Size(50, 30);
Controls.Add(lbluser);
lbluser.Click += new EventHandler(lbluser_Click);
}
}
}
void lbluser_Click(object sender, EventArgs e)
{
LinkLabel lnkClis = (LinkLabel)sender;
Form frm = new Form();
frm.Name = lnkClis.Name;
frm.Text = lnkClis.Text;
frm.Show();
DataGrid dtgrd = new DataGrid();
dtgrd.Location = new System.Drawing.Point(10, 1 * 40);
dtgrd.Name = lnkClis.Name;
names = lnkClis.Name;
TextBox tx = new TextBox();
tx.Location = new System.Drawing.Point(10, 5 * 40);
tx.Size = new Size(80, 30);
tx.Multiline = true;
tx.LostFocus += new EventHandler(tx_LostFocus);
Button btn = new Button();
btn.Location = new System.Drawing.Point(10, 7 * 40);
btn.Size = new System.Drawing.Size(50, 30);
btn.Name = lnkClis.Name;
btn.Click += new EventHandler(btn_Click);
frm.Controls.Add(dtgrd);
frm.Controls.Add(tx);
frm.Controls.Add(btn);
}
// Now I am trying to access the data grid in the btn_click event
void btn_Click(object sender, EventArgs e)
{
Button btsave = (Button)sender;
string eid = btsave.Name;
object grd = btsave.Parent.Controls.Find("dtgrd", true).FirstOrDefault();
((DataGrid)grd).DataSource = ds.Tables[0];
}
Now I am getting an error object set of instances of an object at:
((DataGrid)grd).DataSource = ds.Tables[0];
The exception message you have written:
Now I am getting an error object set of instances of an object at
makes no sense, but it looks like
Object reference not set to an instance of an object
If this is the case, I think the error lays in Find method call. According to documentation:
Searches for controls by their Name property and builds an array of all the controls that match.
In your button click handler you assume that grid is called dtgrd, but while you create a grid you name it like this:
dtgrd.Name = lnkClis.Name;
it will suffice if you change this line to:
dtgrd.Name = "dtgrd";
Having said that, you should consider using an anonymous method for the button click handler. It will eliminate need for calling the Find method in the first place.
void lbluser_Click(object sender, EventArgs e)
{
//...
DataGrid dtgrd = new DataGrid();
//...
Button btn = new Button();
//...
btn.Click += (sender,args)=> dtgrd.DataSource = ds.Tables[0];
Try the following code
public Form1()
{
Form f1 = new Form();
f1.Text = "New Form";
TextBox t1 = new TextBox();
t1.Top = 0;
t1.Name = "t1";
t1.Visible = true;
f1.Controls.Add(t1);
Button b1 = new Button();
b1.Top = 30;
b1.Name = "b1";
b1.Text = "Click";
b1.Click += b1_Click;
f1.Controls.Add(b1);
f1.Show();
}
public void b1_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
object txt = btn.Parent.Controls.Find("t1", false).First();
((TextBox)txt).Text = "Hi, you have clicked me.";
}
I modified Nitesh's code a bit. Just capture the textbox in the click handler using a lambda:
public Form1()
{
Form f1 = new Form();
f1.Text = "New Form";
TextBox t1 = new TextBox();
t1.Top = 0;
t1.Name = "t1";
t1.Visible = true;
f1.Controls.Add(t1);
Button b1 = new Button();
b1.Top = 30;
b1.Name = "b1";
b1.Text = "Click";
b1.Click += (sender, args) => MessageBox.Show("The text is: " + t1.Text);
f1.Controls.Add(b1);
f1.Show();
}
The error you are getting is from the statement (as the grd object is null):
((DataGrid)grd).DataSource = ds.Tables[0];
Since you are trying to catch hold of a dynamic control, it's good have a proper null checks, type checks, and error handling. Something like this:
if(grd != null && grd is DataGrid)
((DataGrid)grd).DataSource = ds.Tables[0];
If I start my form, write something in my textbox and then try to get the textbox value, then I get null. How can I get the textbox value? If I add a button and try to get the value, then it works. But I'm trying to do it without the button. I am using a WPF form. This is my code:
public partial class _2band : Page
{
public _2band()
{
InitializeComponent();
UpdateLayout();
RFIDI();
vardasBox1.Text = "";
dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Start();
}
// MainWondow mainas = new MainWondow();
DB db = new DB();
string pavad;
string vardas;
int status;
string s = "";
string s0 = "";
RfidApi Api = new RfidApi();
private System.Windows.Threading.DispatcherTimer dispatcherTimer;
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
Api.nuskaitymas(out s0);
if (s0 != null)
{
s = s0;
vardas = vardasBox1.Text;
}
}