c# - how to change button image on all my forms - c#

I have got three forms and on one of them there is a combobox which is supposed to change icons on all my running forms and images of buttons located on another forms, when selected value of the combobox is changed.
Please note that the problem is solved when it comes to changing icons, but I need solution for changing buttons images. I have managed to do so on just one form (where the combobox is located). I cannot figure out how to customise buttons on other forms as well.
I have tried this way:
private void combo_Theme_SelectedValueChanged(object sender, EventArgs e)
{
Main f1 = new Main();
if (combo_Theme.Text == "Purple")
{
foreach (var form in Application.OpenForms.Cast<Form>())
{
form.Icon = Properties.Resources.Purple;
f1.btn_Exit.Image = Properties.Resources.EXIT_purple;
}
}
... but had no success.
Basically, I am stuck now, since the code above doesn't work for me.
Any ideas?

You should re-design your forms by implementing some interface with some method, calling that method will actually update the images of the buttons on a specific form. That way you don't have to loop through each controls (in nested relationship) and check out every button. However if your forms don't have complex nested relationship and the number of buttons is small, we can use the following code, in fact this code still works OK (responsive enough) when you have thousands of controls on a form with several nested containers):
public IEnumerable<Button> GetAllButtons(Form form){
Stack<Control> controls = new Stack<Control>();
controls.Push(form);
while(controls.Count > 0){
var control = controls.Pop();
foreach(var c in control.Controls){
if(c is Button) yield return c;
controls.Push(c);
}
}
}
//now use that method in your code like this:
private void combo_Theme_SelectedValueChanged(object sender, EventArgs e)
{
Main f1 = new Main();
if (combo_Theme.Text == "Purple")
{
foreach (var form in Application.OpenForms.Cast<Form>())
{
form.Icon = Properties.Resources.Purple;
f1.btn_Exit.Image = Properties.Resources.EXIT_purple;
//looping through each button on the current form
foreach(var button in GetAllButtons(form)){
//your code here
button.Image = Properties.Resources.EXIT_purple;
}
}
}
//...
}

Related

All buttons state change in C# [duplicate]

This question already has answers here:
How to get ALL child controls of a Windows Forms form of a specific type (Button/Textbox)?
(28 answers)
Closed 2 years ago.
What I am trying to do is to change background color of the button once it's active. So far I achieved it by this way:
private void button3_Click(object sender, EventArgs e) // METEO BUTTON
{
DefaultButtons();
button3.BackColor = Color.LimeGreen;
// REST OF THE CODE HOES HERE
}
While DefaultButtons function is like this:
public void DefaultButtons()
{
List<Button> buttonsToDefualt = new List<Button>()
{
// MAIN MENU
button1,
button2,
[...]
buttonX
};
foreach (var item in buttonsToDefualt)
{
item.BackColor = Color.Green;
}
}
Now swapping buttons works like this: Change entire list to default color, then activated button change color to LimeGreen. It would be fine but:
1) I have to launch DefaultButtons(); for EACH button Click
2) I have to manually add all buttons to list, and now I have more than 120 buttons (Yeah, building custom interface...), and keep adding that by hand is tiring.
I tried this:
void DefaultButtonsNew()
{
foreach (Button b in this.Controls)
{
if (b != null)
{
b.BackColor = Color.Green;
}
}
}
But I've got an Exception: System.InvalidCastException: 'Can't throw object 'System.Windows.Forms.SplitContainer' on type 'System.Windows.Forms.Button'.'
If you're looking for a way to reset all buttons on the form, and some buttons are inside other containers, then we need to recursively loop through each control's Controls collection to find all the buttons.
One easy way to do that is to write a method that takes in a container (like the form), iterates through its Controls collection, changes the BackColor of any Button controls, and calls itself for the other control types:
private void ResetButtons(Control container)
{
// Loop through each control in this container
foreach (Control control in container.Controls)
{
var button = control as Button;
// If the control is a button, change it's backcolor
if (button != null) button.BackColor = Color.Green;
// Otherwise check it's controls collection (recursive call)
else ResetButtons(control);
}
}
Next, it sounds like you're looking for a way to avoid writing out a call to this method, and to change the BackColor of the current button, in every button click event.
One easy way around this is to simply add this method, and the BackColor change, to every button click in code. We can write a method to do this using a similar pattern - loop through every control in every container, and if it's a button, add a method to it's click event:
private void HookupButtonClickEvent(Control container)
{
// Loop through each control in this container
foreach (Control control in container.Controls)
{
var button = control as Button;
// If the control is a button, add a method to it's click event
if (button != null)
{
button.Click += (s, e) =>
{
ResetButtons(container);
button.BackColor = Color.LimeGreen; // Change this button's color
};
}
// Otherwise check it's controls collection (recursive call)
else HookupButtonClickEvent(control);
}
}
Now, all we have to do is call the ResetButtons and HookupButtonClickEvent in our form's constructor, and every button will start with the same backcolor and will have our reset method call in it's click event:
public Form1()
{
InitializeComponent();
HookupButtonClickEvent(this);
ResetButtons(this);
}
Note that this does not prevent you from adding additional click events to the buttons. It merely provides a way to hook up the common functionality to all buttons without writing a bunch of duplicated code.
You can still double-click the controls on your form to add other Click event handlers:
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Button one clicked - doing something unique here");
}
private void button2_Click(object sender, EventArgs e)
{
MessageBox.Show("Button two clicked - doing something else here");
}
The iterator on Controls collection returns all the controls and trying to cast it to Button should an do fail.
Change your method like this:
void DefaultButtonsNew()
{
foreach (Control b in this.Controls)
{
if (b is Button)
{
b.BackColor = Color.Green;
}
}
}

Pop-up window in a WPF application

I've a C# WPF application which show uses Grid control in the xaml(P screen).For every row in the grid, I've a column called Details.Clicking on item in this column shows a pop-up windows which also has a grid in the xaml(C screen).
My item click event in the P's viewmodel has the following code:
var myChildWindow = new MyGridView();
myChildWindow.Show();
If the user clicks on the item multiple times, I just want to highlight the existing C pop-up window.If there's no existing windows open, then only I want to open a new windows.
I've worked on a similar requirement for Winforms applicaiton.How do I go about this for a WPF application please?
Thanks.
First you'd need to declare myChildWindow outside of the click event so that it is accessible from multiple events. So,
MyGridView myChildWindow;
goes outside the click event, probably as a private variable.
Then, in your click event see if it's null, and if it is, create it.
if (myChildWindow == null)
{
myChildWindow = new MyGridView();
myChildWindow.Show();
}
You could keep a reference to the window and get rid of this when the window is closed:
MyGridView myChildWindow;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (myChildWindow == null)
{
myChildWindow = new MyGridView();
myChildWindow.Closed += MyChildWindow_Closed;
myChildWindow.Show();
}
else
{
myChildWindow.Activate();
}
}
private void MyChildWindow_Closed(object sender, EventArgs e)
{
myChildWindow.Closed -= MyChildWindow_Closed;
myChildWindow = null;
}

refreshing treeview component from other form

I currently have a class that handles my treeview and other winForm components.
I want to use another form which act as my input and once I press the save button it should update my treeview component on the other form. So far what I tried has not worked.
here is my code:
*mainDisplay is my form which includes my component and stores my variable that holds the data
Here I load my date into the treeview
public void mainDisplay_Load( TreeNode input)
{
treeView1.BeginUpdate();
foreach (data x in mydata1)
{
Console.WriteLine(x.getName());
if (x.getName() != null)
{
treeView1.Nodes.Add(input);
}
}
treeView1.Refresh();
}
here is my button action on the OTHER form:
private void button1_Click(object sender, EventArgs e)
{
if (!(String.IsNullOrEmpty(getnamebox.Text))) ;
{
mainDisplay putdata = new mainDisplay();
name = getnamebox.Text;
pass = getpassbox.Text;
url = geturlbox.Text;
notes = getnotebox.Text;
data newData = new data(name, pass, notes);
mainDisplay.mydata1.Add(newData);
TreeNode mytree = new TreeNode(name);
putdata.mainDisplay_Load(mytree);
this.Hide();
}
Any tip would be appreciated.
You just created a brand new main display form somewhere (in memory) and added a tree node to it.
You need to pass the reference of your main display forward (usually in an initialize function or trace back your second form's parentage depending on how your stuff was set up) and then use the reference to your actual main form to update the tree.

Find Control in collection - event ControlAvailable Disabled

In my lightswitch app i need to add a small image control to every row, when clicking on it , it should send you to a detail screen. I made the silverlight control and added it to the lightswitch app.
partial void VidContentItemRessources_Loaded(bool succeeded) {
int index = 0;
foreach (VidContentItemRessourcesItem cust in this.VidContentItemRessources) {
this.FindControlInCollection("ImageLinkIcon", this.VidContentItemRessources.ElementAt(index))
.ControlAvailable += (s, e) => {
MyLinkImage = (e.Control as LinkImage);
MyLinkImage.MouseLeftButtonDown += MyLinkImage_MouseLeftButtonDown;
};
index++;
}
}
But if i do this i get an error that the event control available can't be used on controls in collection ..
So i tried to do it like this
LinkImage neco = this.FindControlInCollection("ImageLinkIcon", this.VidContentItemRessources.ElementAt(index)) as LinkImage;
neco.MouseLeftButtonDown += MyLinkImage_MouseLeftButtonDown;
But then neco is allways null because it is trying to load the control before it's available... any solution pls ?
These types of initialisations should go in the screen's Created method, that way you're guaranteed that all of the controls on the screen have been created. If any of the screen's methods (like InitializeDataWorkspace, Created, Saving etc) aren't in your code file, you can create them by using the Write Code dropdown box in the screen editor.
I solved it like this:
I catching click event in silverlight control than i invoking method in lightsiwtch
public void MouseClick(object sender, MouseButtonEventArgs e) {
var objDataContext = (IContentItem)this.DataContext;
var Screen = (Microsoft.LightSwitch.Client.IScreenObject)objDataContext.Screen;
Screen.Details.Dispatcher.BeginInvoke(() => {
Screen.Details.Methods["DoImageLinkEvent"]
.CreateInvocation(null).Execute();
});
}

How to use "for" to set the background image of a group of buttons in a C# Windows Forms application

I want to use a wheel to change (for example) 30 buttons' background image each time a form loads.
I cannot use this:
for(int i=1;i<=30;i++)
{
button i .backgroundimage=image.fromfile("URL");
}
What should I do?
There are many possible interpretations of your problem. Why can't you use your code? There are also different solutions for your problem.
As example:
public Form1() // Constructor
{
InitializeComponent(); // Ensure all controls are created.
List<Button> buttons = new List<Button>(30);
buttons.Add(mybutton1)
buttons.Add(mybutton2)
// Go futher with all your buttons.
}
private void Form1_Load(object sender, System.EventArgs e) // Create a load event
{
foreach(Button button in buttons)
{
button.BackgroundImage = Image.FromFile(path);
// Note: The file remains locked until the Image is disposed!
}
}
Well you could use something like this assuming this code executes in a Form_Load and the buttons Parent control is your form. Have in mind that you should supply the real path to your image that you want to set as a background image
string path = "rootNameOfTheImage";
int counter = 0;
foreach(Control ctrl in this.Controls)
{
if(ctrl is Button)
{
Button btn = (Button)ctrl;
if(/* test if this button should be used */)
{
btn.BackgroundImage=Image.FromFile(path + counter++.ToString() + ".jpg");
}
}
}

Categories

Resources