I am working on the following code:
private Label textLabel;
public void ShowDialog()
{
Form prompt = new Form();
prompt.Width = 500;
prompt.Height = 150;
prompt.Text = caption;
textLabel = new Label() { Left = 50, Top=20, Text="txt"};
TextBox textBox = new TextBox() { Left = 50, Top=50, Width=400 };
Button confirmation = new Button() { Text = "Ok", Left=350, Width=100, Top=70 };
confirmation.Click += (sender, e) => { prompt.Close(); };
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.Controls.Add(textBox);
prompt.ShowDialog();
}
I am calling the above method using another method and trying to update the textLabel field inside a loop like this
public void doIt()
{
ShowDialog();
for(int i=0;i<10;i++)
{
textLabel.TEXT = ""+i;
Threading.Thread.Sleep(1000);
}
}
That is the way we do in Java, but in C# it I could not update the label text in this way. What is wrong here and why can't I update the text?
So this is how I would do it, it is not a complete solution but I hope it will point you in the right direction:
Make the Prompt class that will derive from the Form. Add the controls to it (I did it manually but you could use the designer). Add the Timer which will be triggered on each second and which will change the label's text. When the counter hits 10 stop the timer.
public partial class Prompt : Form
{
Timer timer;
Label textLabel;
TextBox textBox;
Button confirmation;
int count = 0;
public Prompt()
{
InitializeComponent();
this.Load += Prompt_Load;
this.Width = 500;
this.Height = 150;
textLabel = new Label() { Left = 50, Top = 20, Text = "txt" };
textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70 };
this.Controls.Add(confirmation);
this.Controls.Add(textLabel);
this.Controls.Add(textBox);
timer = new Timer();
timer.Interval = 1000;
timer.Tick += timer_Tick;
}
void Prompt_Load(object sender, EventArgs e)
{
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
this.textLabel.Text = " " + count.ToString();
count++;
if (count == 10)
timer.Stop();
}
}
In the doIt method, create the instance of your Prompt form, set its caption and call its ShowDialog() method.
public void doIt()
{
Prompt p = new Prompt();
p.Text = caption;
p.ShowDialog();
}
Related
I want to create a lot of Labels and Buttons and to make this task easier and more dynamic I initialized these in a for loop in a pure C# Page (Page.cs).
How can I manipulate a specific Label with a Button_Clicked Event (in my case the Label with the index i, which has been created together with the Button in the for loop)?
Here is a summary of my problem:
// Constructor
public Page()
{
Label[] lb = new Label[10];
Button[] btn = new Button[lb.Length];
for (int i = 0; i < lb.Length; i++)
{
lb[i] = new Label();
btn[i] = new Button();
btn[i].Clicked += Button_Clicked;
// TODO Somehow reference the Label in the Button Clicked Method
}
// set Content ...
}
// Buton Clicked Method
private void Button_Clicked(object sender, EventArgs e)
{
lb[i].Text = "Hello World!";
// lb[i] should be the Label, which was initialized with the Button in the for loop
}
or is there a better way, to achieve my goal?
You may manipulate a specific Label with a Button_Clicked Event by wrapping a pair of button and label into one StackLayout and adding a ClassId property to each StackLayout.
The sample code is like this:
public partial class MainPage : ContentPage
{
Label[] lb;
Button[] btn;
StackLayout[] sl;
int i = 0;
public MainPage()
{
InitializeComponent();
sl = new StackLayout[10];
lb = new Label[10];
btn = new Button[lb.Length];
StackLayout content = new StackLayout();
for (i = 0; i < lb.Length; i++)
{
lb[i] = new Label()
{
Text = "Old Text"+i,
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.Center
};
btn[i] = new Button
{
Text = "Click to Change Label Text!"+i,
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.Center,
};
btn[i].Clicked += (sender, e) => Button_Clicked(sender, e);
// TODO Somehow reference the Label in the Button Clicked Method
sl[i] = new StackLayout
{
ClassId = ""+i,
Children =
{
lb[i],
btn[i]
}
};
content.Children.Add(sl[i]);
}
Content = content;
}
// Buton Clicked Method
private void Button_Clicked(object sender, EventArgs e)
{
Button bt = sender as Button;
StackLayout layout = bt.Parent as StackLayout;
int index = Int32.Parse(layout.ClassId);
lb[index].Text = "Hello World!" + index;
}
}
The result is like this:
If you only have 10 labels, I would just use lambdas.
Label[] lb = new Label[10];
Button[] btn = new Button[lb.Length];
for (int i = 0; i < lb.Length; i++)
{
lb[i] = new Label();
btn[i] = new Button();
btn[i].Clicked += (s,e) => { lb[i].Text = "hello world" };
}
One of the ways to achieve this is to modify event handler during the registration.
for (int i = 0; i < lb.Length; i++)
{
lb[i] = new Label();
btn[i] = new Button();
btn[i].Clicked += (sender, e) => Button_Clicked(sender, e, i);
//Here i is to pass the index to event handler Button_Clicked;
}
And now, you could access index in button clicked event handler and you could access the label with the index passed.
When I click on a button in my Floqlayoutpanel they should hide at the place where I clicked on them. But instead they disappear and all the other buttons move.
They should hide at their place
But this is what happens
How I create my Buttons:
private void CreateButton()
{
int buttonIndex = 0;
for (int i = 0; i < 16; i++)
{
Button button = new Button();
button.Name = $"Button_{buttonIndex}";
button.Width = 100;
button.Height = 100;
button.Click += OnButtonClick;
button.BackgroundImage = BackSideImage();
flowLayoutPanel1.Controls.Add(button);
buttonIndex++;
}
}
How I hide my Buttons:
private void CompareCards()
{
if (clickedCards.Count >= 3)
{
if (clickedCards[0].PairIndex == clickedCards[1].PairIndex)
{
clickedCards[0].Button.Hide();
clickedCards[1].Button.Hide();
}
else
{
clickedCards[0].Button.BackgroundImage = BackSideImage();
clickedCards[1].Button.BackgroundImage = BackSideImage();
}
clickedCards.Clear();
}
}
Instead of hiding your button, you can make it invisible like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
for (int x = 0; x < 9; x++)
{
var button = new Button
{
Name = "Test-" + x,
Text = "Test-" + x,
Width = 100,
Height = 100
};
button.Click += OnButtonClick;
flowLayoutPanel1.Controls.Add(button);
}
}
private void OnButtonClick(object sender, EventArgs e)
{
//Instead of this...
//((Button)sender).Hide();
//Do this...
var button = ((Button) sender);
button.FlatStyle = FlatStyle.Flat;
button.FlatAppearance.BorderColor = BackColor;
button.FlatAppearance.MouseOverBackColor = BackColor;
button.FlatAppearance.MouseDownBackColor = BackColor;
button.Text = string.Empty;
button.Enabled = false;
}
}
Background: I want to show a custom message box to the user with Yes/No buttons and if the user clicks each of these buttons I will return the result to the caller. Also, if the user doesn't show any reaction again I want to return a third result (using a Timer event). In a word, either after some time elapsed or after a button click the method (Display in my code) should return a value; and I want to wait for either of them to happen.
Problem: The UI looks frozen and only the Timer event triggers.
Code which will be used in the real project (with descent names!):
namespace MessageBox
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MyForm.Display();
}
}
public class MyForm : Form
{
public MyForm()
{
List<Button> _buttonCollection = new List<Button>();
FlowLayoutPanel _flpButtons = new FlowLayoutPanel();
Panel _plFooter = new Panel();
_plFooter.Dock = DockStyle.Bottom;
_plFooter.Padding = new Padding(5);
_plFooter.BackColor = Color.FromArgb(41, 47, 139);
_plFooter.Height = 75;
this.FormBorderStyle = FormBorderStyle.None;
this.BackColor = Color.FromArgb(20, 37, 105);
this.StartPosition = FormStartPosition.CenterScreen;
this.Padding = new Padding(3);
this.Width = 400;
_flpButtons.FlowDirection = FlowDirection.RightToLeft;
_flpButtons.Dock = DockStyle.Fill;
_plFooter.Controls.Add(_flpButtons);
this.Controls.Add(_plFooter);
Button btnYes = new Button();
btnYes.Click += ButtonClick;
btnYes.Text = "Yes";
Button btnNo = new Button();
btnNo.Click += ButtonClick;
btnNo.Text = "No";
_buttonCollection.Add(btnYes);
_buttonCollection.Add(btnNo);
foreach (Button btn in _buttonCollection)
{
btn.ForeColor = Color.FromArgb(170, 170, 170);
btn.Font = new System.Drawing.Font("Eurostile", 12, FontStyle.Bold);
btn.Padding = new Padding(3);
btn.FlatStyle = FlatStyle.Flat;
btn.Height = 60;
btn.Width = 150;
btn.FlatAppearance.BorderColor = Color.FromArgb(99, 99, 98);
_flpButtons.Controls.Add(btn);
}
}
static Task taskA;
private void ButtonClick(object sender, EventArgs e)
{
_event.Set();
Button btn = (Button)sender;
if (btn.Text == "Yes")
Result = 1;
else
{
Result = 2;
}
this.Close();
this.Dispose();
}
static AutoResetEvent _event = new AutoResetEvent(false);
private static MyForm form;
public static int Display()
{
form = new MyForm();
StartTimer();
form.Show();
_event.WaitOne();
form.Close();
form.Dispose();
return Result;
}
private static void StartTimer()
{
_timer = new System.Timers.Timer(10000);
_timer.Elapsed += SetEvent;
_timer.AutoReset = false;
_timer.Enabled = true;
}
private static System.Timers.Timer _timer;
public static int Result { get; set; }
private static void SetEvent(Object source, System.Timers.ElapsedEventArgs e)
{
_timer.Start();
Result = -1;
var timer = (System.Timers.Timer) source;
timer.Elapsed -= SetEvent;
_event.Set();
}
}
}
Note: I know the problem is that the UI control is created in a thread which is frozen but what's the solution?
Create a Dialog for MessageBox at the end of your process and show the alert you want to show the user.
You can look at the sources like and issue with Thread
I am developing a windows form application. Creating a UI for some service. What is happening is when I created the application there are various buttons on which a single click should work to get and set the value but after the completion of code all those buttons are reacting on double click.
when we apply some break point and test, values get and set in single click only but during run-time it need double click. Can anybody help?
I got the solution by writing a piece of code.
Just activated the button on first click.
bool firstClick = true;
{if(firstClick) { button.select(); //Activating the button } }
Thanks all for your responses.
Here is a full Article from MSDN on how to use single-click only vs double-click only. Also, it states how you can handle events and differentiate between a single click and a double click.
The article uses boolean and timers to do that. You might need to use a Dictionary<Button, boolean> if you have multiple buttons. Hope it helps.
Here is the example if the link got down or removed for some reaosn:
Handle the MouseDown event and determine the location and time span
between clicks using the appropriate SystemInformation properties and
a Timer component. Perform the appropriate action depending on whether
a click or double-click takes place. The following code example
demonstrates how this can be done.
class Form1 : Form
{
private Rectangle hitTestRectangle = new Rectangle();
private Rectangle doubleClickRectangle = new Rectangle();
private TextBox textBox1 = new TextBox();
private Timer doubleClickTimer = new Timer();
private ProgressBar doubleClickBar = new ProgressBar();
private Label label1 = new Label();
private Label label2 = new Label();
private bool isFirstClick = true;
private bool isDoubleClick = false;
private int milliseconds = 0;
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
public Form1()
{
label1.Location = new Point(30, 5);
label1.Size = new Size(100, 15);
label1.Text = "Hit test rectangle:";
label2.Location = new Point(30, 70);
label2.Size = new Size(100, 15);
label2.Text = "Double click timer:";
hitTestRectangle.Location = new Point(30, 20);
hitTestRectangle.Size = new Size(100, 40);
doubleClickTimer.Interval = 100;
doubleClickTimer.Tick +=
new EventHandler(doubleClickTimer_Tick);
doubleClickBar.Location = new Point(30, 85);
doubleClickBar.Minimum = 0;
doubleClickBar.Maximum = SystemInformation.DoubleClickTime;
textBox1.Location = new Point(30, 120);
textBox1.Size = new Size(200, 100);
textBox1.AutoSize = false;
textBox1.Multiline = true;
this.Paint += new PaintEventHandler(Form1_Paint);
this.MouseDown += new MouseEventHandler(Form1_MouseDown);
this.Controls.AddRange(new Control[] { doubleClickBar, textBox1,
label1, label2 });
}
// Detect a valid single click or double click.
void Form1_MouseDown(object sender, MouseEventArgs e)
{
// Verify that the mouse click is in the main hit
// test rectangle.
if (!hitTestRectangle.Contains(e.Location))
{
return;
}
// This is the first mouse click.
if (isFirstClick)
{
isFirstClick = false;
// Determine the location and size of the double click
// rectangle area to draw around the cursor point.
doubleClickRectangle = new Rectangle(
e.X - (SystemInformation.DoubleClickSize.Width / 2),
e.Y - (SystemInformation.DoubleClickSize.Height / 2),
SystemInformation.DoubleClickSize.Width,
SystemInformation.DoubleClickSize.Height);
Invalidate();
// Start the double click timer.
doubleClickTimer.Start();
}
// This is the second mouse click.
else
{
// Verify that the mouse click is within the double click
// rectangle and is within the system-defined double
// click period.
if (doubleClickRectangle.Contains(e.Location) &&
milliseconds < SystemInformation.DoubleClickTime)
{
isDoubleClick = true;
}
}
}
void doubleClickTimer_Tick(object sender, EventArgs e)
{
milliseconds += 100;
doubleClickBar.Increment(100);
// The timer has reached the double click time limit.
if (milliseconds >= SystemInformation.DoubleClickTime)
{
doubleClickTimer.Stop();
if (isDoubleClick)
{
textBox1.AppendText("Perform double click action");
textBox1.AppendText(Environment.NewLine);
}
else
{
textBox1.AppendText("Perform single click action");
textBox1.AppendText(Environment.NewLine);
}
// Allow the MouseDown event handler to process clicks again.
isFirstClick = true;
isDoubleClick = false;
milliseconds = 0;
doubleClickBar.Value = 0;
}
}
// Paint the hit test and double click rectangles.
void Form1_Paint(object sender, PaintEventArgs e)
{
// Draw the border of the main hit test rectangle.
e.Graphics.DrawRectangle(Pens.Black, hitTestRectangle);
// Fill in the double click rectangle.
e.Graphics.FillRectangle(Brushes.Blue, doubleClickRectangle);
}
}
You can simply identify single click and double using a timer. Here is the example
class Form1 : Form
{
Timer timer;
public Form1()
{
InitializeComponent();
timer = new Timer();
timer.Interval = 500;
timer.Tick += new EventHandler(Timer_Tick);
}
private void App_MouseDown(object sender, MouseEventArgs e)
{
if (e.Clicks == 1)
{
timer.Start();
}
else
{
timer.Stop();
doubleClick();
}
}
private void Timer_Tick(object sender, EventArgs e)
{
timer.Stop();
singleClick();
}
//Single click
public void singleClick()
{
MessageBox.Show("Single Click.");
}
//Double click
public void doubleClick()
{
MessageBox.Show("Double Click.");
}
}
Hey there StackOverflow,
I am having an issue with a certain portion of my Windows Store app. This is initially what is displayed...
and this is what happens when the button is clicked
As you can see, the show more button and the original string is still present. I have tried making the "Show More" button update the TextBlock to a "" value and the "Show More" button is still there and clickable. I have also tried clearing the StackPanel and re-adding the items to no avail.
Here is the code I used to do this:
private async void Description_Loaded(object sender, RoutedEventArgs e)
{
await wiki;
if (wiki.Result.ContainsKey("real_name"))
{
TeamInfoTitle.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
TeamDescription.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
PopulateInfo(Description);
}
else if(wiki.Result.ContainsKey("current_members"))
{
CharacterInfoTitle.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
Description.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
PopulateInfo(TeamDescription);
}
}
void expand_Click(object sender, RoutedEventArgs e)
{
HyperlinkButton button = (HyperlinkButton)sender;
button.Content = "Show Less";
button.Click -= expand_Click;
button.Click += shrink_Click;
TextBlock text = (TextBlock)button.Tag;
text.Text = (string)text.Tag;
}
void shrink_Click(object sender, RoutedEventArgs e)
{
HyperlinkButton button = (HyperlinkButton)sender;
button.Content = "Show More";
button.Click -= shrink_Click;
button.Click += expand_Click;
TextBlock text = (TextBlock)button.Tag;
string item = (string)text.Tag;
text.Text = item.Substring(0, item.LastIndexOf(" ", 150, 15)) + "...";
}
private void PopulateInfo(Grid desc)
{
for (int i = 0; i < desc.RowDefinitions.Count; i++)
{
string value;
if (wiki.Result.TryGetValue((desc.Children[i] as TextBlock).Name, out value))
{
FrameworkElement now = new TextBlock() { Text = value, FontSize = 24, TextWrapping = TextWrapping.Wrap };
if (value.Length > 200)
{
TextBlock text = (TextBlock)now;
HyperlinkButton expand = new HyperlinkButton() { Content = "Show More", HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Right, VerticalAlignment = Windows.UI.Xaml.VerticalAlignment.Bottom };
expand.Tag = text;
expand.Click += expand_Click;
StackPanel stack = new StackPanel();
text.Tag = value;
text.Text = value.Substring(0, value.LastIndexOf(" ", 150)) + "...";
stack.Children.Add(text);
stack.Children.Add(expand);
now = stack;
}
Grid.SetRow(now, i);
Grid.SetColumn(now, 1);
now.Margin = new Thickness(0, 0, 0, 10);
desc.Children.Add(now);
}
else
desc.Children[i].Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
}
Any help would be greatly appreciated! Note: Description and TeamDescription are Grids defined in the XAML.
Turns out the XAML code was triggering the loaded event twice, thanks swistak for putting me on the right track!