Toggling the appearance of a button winform - c#

I have a list of buttons in a panel (generated dynamically). In my application, when one of the buttons is clicked, its appearance should change. If the user changes their choice and clicks another button in the list, the new button changes appearance while the old one returns to its default appearance.
A click on a completely unrelated button serves to confirm the choice.
How do I go about this? Changing the appearance is not really the problem but knowing there is a previous selection and reverting is.
Thanks.

Create a Button click event handler for all the Buttons in your Panel and handle all updates there:
private void MyToggleButton_Click(object sender, EventArgs e) {
// Set all Buttons in the Panel to their 'default' appearance.
var panelButtons = panel.Controls.OfType<Button>();
foreach (Button button in panelButtons) {
button.BackColor = Color.Green;
// Other changes...
}
// Now set the appearance of the Button that was clicked.
var clickedButton = (Button)sender;
clickedButton.BackColor = Color.Red;
// Other changes...
}

Can you not use a variable to store the current selected button
Pseudo code
Button b = selectedButton
in the on click event
if b != sender
revert b
b = new selected button

Have a variable that stores the current button, making sure you change the colour of the previously assigned button before assigning a newly clicked button
private Button currentBtn = null;
Create a common event handler for the buttons
protected void b_Click(object sender, EventArgs e)
{
Button snder = sender as Button;
//for the first time just assign this button
if (currentBtn == null)
{
currentBtn = snder;
}
else //for the second time and beyond
{
//change the previous button to previous colour. I assumed red
currentBtn.BackColor = System.Drawing.Color.Red;
//assign the newly clicked button as current
currentBtn = snder;
}
//change the newly clicked button colour to "Active" e.g green
currentBtn.BackColor = System.Drawing.Color.Green;
}

Related

How to change iconbutton to it's default backcolor when clickevent is not performed?

I have 20 iconbuttons in my form. when clickevent is performed i want to change buttons(backcolor,forecolor,Iconcolor) and remaining buttons should revert to it's default color.
public void btn1()
{
foreach (Control c in this.Controls)
{
if (c is Button)
{
(c as Button).ForeColor = Color.White;
(c as Button).BackColor = Color.FromArgb(46, 51, 73);
}
}
}
You can make each button listen to the same Click event and do some conditional logic to achieve this.
First, make each of your buttons reference the same click event. You can do this from the Form Designer by clicking the button and in the Properties window, click the lightening bolt icon (the events icon) and change the Click event to be the method you wish:
Then, make your event method do something like this:
public void ChangeButtonColors(object sender, EventArgs e)
{
//change the color of the clicked button to desired color
Button clickedButton = (System.Windows.Forms.Button)sender;
clickedButton.BackColor = Color.Red;
//change all other buttons to defualt color
foreach (Control c in this.Controls)
{
if (c is Button && c != clickedButton)
{
c.BackColor = Color.Green;
}
}
}
This gets the type of the sender (the clicked button in this case), and sets the BackColor property of it. Then, the foreach loop loops over all of the controls in the form, checks if the current item in the list is a button and is not the button that was clicked, it will change the BackColor property. Obviously, you can change other properties of both the clicked button, and the other buttons in the foreach.
If done properly, this is how it should behave:
This is what RadioButton is good for. Just set its Appearance to Button so it will look like a regular button but will act as a radio button: clicking it unchecks all the other buttons. The Checked property will be true for only the lastly clicked button:

Change Value of a Dynamically Created Text Box when button is clicked C#

I have dynamically created a button using a function I made which is meant to increase the value of another button created using a similar function. I'm able to retrieve the name of the dynamically created textbox, but since it is dynamically created, I can't reference it.
I've tried to pass the textbox through as a parameter, but it doesn't appear that I'm able to pass extra parameters:
Button ButtonDecreaseValue= addButton(ItemName, "-");
TextBox TextBoxItemAmount = addTextBox(ItemName, "0");
So, how would I change the value of textbox one when ButtonRemoveItem is clicked?
I've created an event handler for the button, like so:
ButtonIncreaseValue.Click += new EventHandler(ItemDecreased);
But, inside the event handler, I'm unsure how I would change the textbox name.
private void ItemDecreased(object sender, EventArgs e)
{
Button currentItem = (Button)sender;
int ItemNo = Convert.ToInt32(currentItem.Tag);
DataRow ItemInfo = getItemDetails(ItemNo);
ItemInfo[0].ToString();
}
When clicking the button, the corresponding textbox should decrease in value.
Assuming this is Windows Forms
You said you have the name of the TextBox? You should be able to find it with that.
private void ItemDecreased(object sender, EventArgs e)
{
string textBoxName = HoweverYouGetTheDynamicTextBoxName();
// Assumptions:
// 1. ItemDecreased is a method on a Form or a UserControl.
// 2. There is only one TextBox with the given name in the Form or UserControl.
// 3. The TextBox is added to the Form or UserControl's Controls property.
TextBox tb = Controls.Find(textBoxName, true).OfType<TextBox>().SingleOrDefault();
if (tb is null)
{
// Couldn't find the text box for some reason.
}
// tb references the dynamically created text box.
}

Toggle between hiding and showing RowDetails when DataGridRow is clicked

I have a DataGrid that has RowDetailsVisibilityMode set to "VisibleWhenSelected" so that the RowDetailsTemplate displays when I select a particular row. What I want is to be able to toggle the RowDetails visibility when I click the row again. By default, the RowDetails will be visible so long as its selected, but I want to essentially "unselect" the selected row if I click it again.
After trying a lot of things, I've found a sort of wacky solution that at least makes it so that I can toggle the visibility when I click the row:
private async void DataGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
await Task.Delay(1); //ensures DataGrid.SelectedIndex is what I just clicked, not the previous value
if (DataGrid.SelectedIndex == prevSelectedIndex) { //check if I'm clicking on what's already selected
DataGrid.SelectedIndex = -1; //collapses everything
}
prevSelectedIndex = DataGrid.SelectedIndex; //save current selected index
}
The delay makes sure that the SelectedIndex property is already updated when I check for the selected index. I wish I didn't have to use it - I would be happy to find a better solution.
The problem now, however, is that whenever I click anything in the RowDetails of the selected row, this event fires and the row details disappear again. I want to be able to somehow check that I only expand/collapse the row when I click the row itself, not when I click whatever's in the RowDetailsTemplate. Is that possible? I don't want to use an extra Expander button for each row.
I found a solution to my problem:
In my RowDetailsTemplate under the ContentControl, I added an EventSetter that captured the PreviewMouseDown event:
<EventSetter Event="PreviewMouseDown" Handler="ContentControl_PreviewMouseDown" />
The Handler for the event set a global variable that indicated whether I had clicked on what's in the ContentControl:
private void ContentControl_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
ClickedRowDetails = true;
}
Finally, in my original code, I simply checked whether I had clicked on the ContentControl, or whether it was something else, which in this case, meant it was the row itself:
private async void DataGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
ClickedRowDetails = false; //default assume that we haven't clicked row details
await Task.Delay(1); //wait for other events to fire
if (!ClickedRowDetails) {
if (DataGrid.SelectedIndex == prevSelectedIndex )
{
DataGrid.SelectedIndex = -1;
}
prevSelectedIndex = DataGrid.SelectedIndex;
}
}
So now, I can successfully expand/collapse rows by simply clicking on them, and then I can manipulate whatever's in the RowDetailsTemplate without accidently collapsing the row. This was done without an Expander button.
I think a global boolean variable can do the toggle for you.
public bool Visible = false;
private async void DataGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (Visible == false)
{
await Task.Delay(1); //ensures DataGrid.SelectedIndex is what I just clicked, not the previous value
if (DataGrid.SelectedIndex == prevSelectedIndex)
{ //check if I'm clicking on what's already selected
DataGrid.SelectedIndex = 1; //collapses everything
}
prevSelectedIndex = DataGrid.SelectedIndex; //save current selected index
Visible = true;
}
else
{
await Task.Delay(1); //ensures DataGrid.SelectedIndex is what I just clicked, not the previous value
if (DataGrid.SelectedIndex == prevSelectedIndex)
{ //check if I'm clicking on what's already selected
DataGrid.SelectedIndex = -1; //collapses everything
}
prevSelectedIndex = DataGrid.SelectedIndex; //save current selected index
Visible = false;
}
}

Are there multiple ways to group radio buttons in Windows Forms?

I have a few radio buttons in my form that should all be connected, but I want one of them in a separate container to group it specifically with some other related inputs. Here is the general look:
Is there a way to group the fourth radio button with the other 3 even though it is in its own group box?
Fact that radio buttons are mutually exclusive only when they are within same parent. Being said that I can think of two options.
Let them be in same parent, handle the Paint event of the parent and draw yourself manually giving the impression that they are different groups.
You have to manually manage the mutual exclusion :(
RadioButtons are no magic, they just set the Checked property of other radio's to false behind the scenes.
private List<RadioButton> radioButtons = new List<RadioButton>();
//Populate this with radios interested, then call HookUpEvents and that should work
private void HookUpEvents()
{
foreach(var radio in radioButtons)
{
radio.CheckedChanged -= PerformMutualExclusion;
radio.CheckedChanged += PerformMutualExclusion;
}
}
private void PerformMutualExclusion(object sender, EventArgs e)
{
Radio senderRadio = (RadioButton)sender;
if(!senderRadio.Checked)
{
return;
}
foreach(var radio in radioButtons)
{
if(radio == sender || !radio.Checked)
{
continue;
}
radio.Checked = false;
}
}
They're in different containers, so you're not able to. I think this is a dupe of this question: Radiobuttons as a group in different panels
This question talks about it:
VB.NET Group Radio Buttons across different Panels
You can handle the CheckedChanged event of your radio buttons to accomplish what you need:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.radioButton1.CheckedChanged += new System.EventHandler(this.HandleCheckedChanged);
this.radioButton2.CheckedChanged += new System.EventHandler(this.HandleCheckedChanged);
this.radioButton3.CheckedChanged += new System.EventHandler(this.HandleCheckedChanged);
}
private bool changing = false;
private void HandleCheckedChanged(object sender, EventArgs e)
{
if (!changing)
{
changing = true;
if (sender == this.radioButton1)
{
this.radioButton2.Checked = !this.radioButton1.Checked;
this.radioButton3.Checked = !this.radioButton1.Checked;
}
else if (sender == this.radioButton2)
{
this.radioButton1.Checked = !this.radioButton2.Checked;
this.radioButton3.Checked = !this.radioButton2.Checked;
}
else if (sender == this.radioButton3)
{
this.radioButton1.Checked = !this.radioButton3.Checked;
this.radioButton2.Checked = !this.radioButton3.Checked;
}
changing = false;
}
}
}
All the radio buttons can be in the same parent container. You just need the radio button in question to draw over the top of the group box.
You can put all the radio buttons in the same parent container (group box would go into the parent as well), but configure the location and the z-order of the radio button in question so it's located over the group box and draws on top of it. That will give you the behaviour you want.
To do this in the designer, to get the radio button on top of the group box (you can't drag/drop it or the designer will put it in the group box), first add the group box, then add the radio button to the parent contjust drop it in the parent container, select it, then move it into position using the arrow keys on your keyboard.
Make sure to right click on it and "bring to front" and/or send the group box to the back, so they draw in the correct order.
** a more hacky way is just to edit the designer generated code - delete the line of code that adds the radio button to the group box's control collection, add line of code to add it to the parent container's control collection instead, and handle location and z-oder with similar lines of code.

how to hide or show image with just one button click event

I am adding the button and image element using code. My wpf application is able to display an image stored on my project when I click the button. I want to hide the displayed image if I clicked the button again. How will I be able to achieve this if I only have one event handler for my button?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
grid_parent.RowDefinitions.Add(new RowDefinition { Height = new GridLength(150, GridUnitType.Pixel) });
grid_parent.RowDefinitions.Add(new RowDefinition { Height = new GridLength(150, GridUnitType.Auto)});
Button btn_submit = new Button { Content = "Submit" };
btn_submit.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
Grid.SetRow(btn_submit, 1);
btn_submit.Click += btn_submit_Click;
grid_parent.Children.Add(btn_submit);
}
void btn_submit_Click(object sender, RoutedEventArgs e)
{
image = new Image { Source = new BitmapImage(new Uri(#"/AddControlsThroughClass;component/images/julie.jpg", UriKind.Relative)) };
image.Stretch = Stretch.Uniform;
Grid.SetRow(image, 0);
grid_parent.Children.Add(image);
}
}
The Button control has no notion of when it has been clicked. Instead of using a regular Button, it would make more sense for you to use a ToggleButton, which does know when it has been clicked. The ToggleButton class has an IsChecked property that will be set to true after the first click and back to false after another click. Therefore there is a very simple solution using this ToggleButton property:
image.Visibility = toggleButton.IsChecked ? Visiblity.Visible : Visiblity.Collapsed;
You can do it by a button however you can do also with keypreview property
Here is a code with keypreview
private void HideShow(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.S)
pictureBox1.Visible = true;
else if (e.KeyCode == Keys.H)
pictureBox1.Visible = false;
}
From the properties of your form add to keydown propery you can hide and show your picture
Or you can do by a button
by this code
pictureBox1.Visible = !pictureBox1.Visible
each time you click the button it will be visible or invisible)

Categories

Resources