How to call a method after a WPF window is closed? - c#

I've got a couple of Controls linked as follows:
ProductSearchControl (UserControl) [contains SearchProducts()]
--ProductListControl (UserControl)
--ProductResultPanel(UserControl)
|
|
|
ProductDetailsWindow (Window)
Within ProductResultPanel.xaml.cs, the following method gets called on a Button click.
void OnModifyPrice(object sender, RoutedEventArgs e)
{
if (this.ModifyPrice != null)
{
ProductDetailsWindow win = new ProductDetailsWindow(this.productId);
win.ShowInTaskbar = false;
win.WindowStartupLocation = WindowStartupLocation.CenterScreen;
win.Owner = Window.GetWindow(this);
bool? result = win.ShowDialog();
}
}
On the ProductDetailsWindow, if I click on a Button, I want to execute the SearchProducts() within ProductSearchControl but I'm currently having difficulty.
Within ProductDetailsWindow.xaml.cs
private void OnCancel(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
}
private void OnSave(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
So after clicking the Save button, I am returned to ProductResultPanel but I don't know how to call the SearchProducts().
Is this possible and if so, any help would be appreciated?

The Window still exists, even after you close it, and you can access its public properties and methods from ProductResultPanel.xaml.cs. Example:
var x = win.SomePublicProperty;
var y = win.GetProducts();
// whatever you need and provide access to in ProductDetailsWindow

Related

C# - How to find out which dynamic button was clicked?

I am writing a program where I dynamically add buttons, I do that by storing them in a Dictionary to get a certain value from them later on (the color of the background).
I need to set a Click event on every one of them, but every Click event has to be a little different, as by clicking the button, a ColorDialog pops up and changes the background of the button.
Is there a way to know which button I clicked? In the following code, the button1 click event adds the other buttons and sets the EventHandler for each of them, what should be the code for the EventHandler? Thank you so much in advance guys.
int i = 0;
Dictionary<int, Button> buttonDictionary = new Dictionary<int, Button>();
Dictionary<int, ColorDialog> colorsDictionary = new Dictionary<int ColorDialog>();
public void button1_Click(object sender, EventArgs e)
{
i++;
buttonDictionary.Add(i, new Button());
buttonDictionary[i].Click += new EventHandler(Click);
this.Controls.Add(buttonDictionary[i]);
}
public void Click(object sender, EventArgs e)
{
//Somehow get the int key of the button that was clicked???? (in this case: int j)
int j;
if (!colorsDictionary.ContainsKey(j))
{
colorsDictionary.Add(j, new ColorDialog());
}
if (colorsDictionary[j].ShowDialog() == DialogResult.OK)
{
buttonDictionary[j].BackColor = colorsDictionary[j].Color;
}
}
The code is made just for adding the buttons, I will be glad for any kind of help, thank you guys!
Well, a direct answer to your question is: cast the sender to a Button
Button pressedButton = (Button) sender;
and then check to which button of the dictionary it matches:
foreach (var entry in buttonDictionary)
{
if (entry.Value == pressedButton)
{
j = entry.Key;
break;
}
}
However, that's overly complex for what you want to achieve. It would be much easier if you had a direct relationship between the button and the color picker:
Dictionary<Button, ColorDialog> buttonDictionary = new Dictionary<Button, ColorDialog>();
Then fill it like this:
public void button1_Click(object sender, EventArgs e)
{
i++;
var button = new Button();
this.Controls.Add(button);
button.Click += new EventHandler(Click);
buttonDictionary.Add(button, null);
}
And later access it with
public void Click(object sender, EventArgs e)
{
Button pressedButton = (Button) sender;
ColorDialog dialog = buttonDictionary[pressedButton];
if (dialog == null)
{
dialog = new ColorDialog();
buttonDictionary[pressedButton] = dialog;
}
if (dialog.ShowDialog() == DialogResult.OK)
{
pressedButton.BackColor = dialog.Color;
}
}
Even more, the question is why you would need so many ColorDialgos, since it should be possible with one dialog only. You can get rid of i, j, all dictionaries and most handling as well. IMHO, the following should be sufficient:
public void button1_Click(object sender, EventArgs e)
{
var button = new Button();
Controls.Add(button);
button.Click += Click;
}
public void Click(object sender, EventArgs e)
{
Button pressedButton = (Button) sender;
ColorDialog dialog = new ColorDialog {Color = pressedButton.BackColor};
if (dialog.ShowDialog() == DialogResult.OK)
{
pressedButton.BackColor = dialog.Color;
}
}
Bonus info:
I don't exactly know what you want to achieve. But your buttons will all be in the same place, overlapping each other. To avoid this, drag a flow layout panel onto the form and then add the buttons to the flow layout:
flowLayoutPanel1.Controls.Add(button);
This will ensure that your buttons are nicely arranged.

WinForm method does not have access to panel properties

I'm trying to make a WinForm app with a expandable menu. I'm trying to create a method that will change a panel propierties in form1 but it sees the value as false even if it is not? I got message box with "recognition as false". Instead of code I would rather a nice explanation
private void JobSelectButton_Click(object sender, EventArgs e)
{
//button to open a panel with "menu"
if (jobPanel.Visible == false)
{
// the panel is visible from this point
jobPanel.Visible = true;
}
else
{
jobPanel.Visible = false;
}
}
public void fla(bool flag)
{ //method inside form1 and it should make jobPanel.Visible = false
if (jobPanel.Visible == false)
MessageBox.Show("recognition as false");
else jobPanel.Visible = false;
}
private void notification_MouseClick(object sender, MouseEventArgs e)
{ // user control that will call the method
caseNBvalue = lbl_caseNB.Text;
profile f2 = new profile();
f2.fla(true);
}

Make event for any panel c#

So I have a matrix of panels (maybe will change for Picture Boxes in the future), and what i want is that every time i press one of the panels after pressing the button on the toolbox it will change it's background to a certain picture.
Right now what i have is:
private void EtapaInicial_Click(object sender, EventArgs e)
{
EtapaInicialWasClicked = true;
}
private void panel_Click(object sender, EventArgs e)
{
if (EtapaInicialWasClicked)
{
panel1.BackgroundImage = Symbols.EtapaInicialbm;
EtapaInicialWasClicked = false;
}
}
What I would like to change was the panel1 to make it work for every panel (otherwise it will only change panel1 independently of the panel i've clicked), is that possible?
Try the following
private void EtapaInicial_Click(object sender, EventArgs e)
=> EtapaInicialWasClicked = true;
private void panel_Click(object sender, EventArgs e)
{
if (EtapaInicialWasClicked)
{
(sender as Panel).BackgroundImage = Symbols.EtapaInicialbm;
EtapaInicialWasClicked = false;
}
}
Yes it is. You have to loop through each panel
and assign the same event handler but you have to make some changes in the event handler itself
foreach(var p in allPanels)
{
p.Click += panel_Click;
}
Then change your event handler like this
private void panel_Click(object sender, EventArgs e)
{
var p = (Panel)sender;
if (EtapaInicialWasClicked)
{
p .BackgroundImage = Symbols.EtapaInicialbm;
EtapaInicialWasClicked = false;
}
}
Remember the sender argument contains reference to the actual control that initiated the event but you have to cast it first in order to use it.
However if you want to store more data for the event you've just handled you can use the panel.Tag property. This can be used to store EtapaInicialWasClicked for example

Click on a button within LongListSelector Windows phone 8

I have a LonglistSelector which displays a list a items, each item has a button:
My LongListSelector has a SelectionChanged event
private void MyLLS_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var item = (MyItemType)MyLLS.SelectedItem;
// Job 1 goes here
}
and each button in a item within LLS has a click event:
private void btDownload_Click(object sender, RoutedEventArgs e)
{
var button = (MyItemType)(sender as Button).DataContext;
// Job 2 goes here
}
Problem is, when i click a button, it'll process the job 2, and after that it'll process Job 1. So how can I just do the job2 of click-button event?
You should use a Boolean flag to determine it, just like:
bool isBtnClicked = false;
private void MyLLS_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// check if button is clicked, if so, return and reset the isBtnClicked flag.
if (isBtnClicked)
{
isBtnClicked = false;
return;
}
var item = (MyItemType)MyLLS.SelectedItem;
// Job 1 goes here
}
private void btDownload_Click(object sender, RoutedEventArgs e)
{
var button = (MyItemType)(sender as Button).DataContext;
// set it true when button clicked
isBtnClicked = true;
// Job 2 goes here
}

CheckBox button and ContextMenuStrip for dropdown menu

I'm tring to implement a button which have a dropdown menu when checked and this menu is gone when unchecked. My problem is I cannot uncheck the checkbox when it or its menu lost focus.
The checkbox's appearance mode is button.
My code:
private void cbSettings_CheckedChanged(object sender, EventArgs e)
{
if (cbSettings.Checked) {cmsSettings.Show(cbSettings, 0, cbSettings.Height);}
else {cmsSettings.Hide();}
}
I've tried to uncheck the checkBox on contextMenuStrip's VisibleChanged / Closed event but this caused menu not to hide (or hide and show immediately).
The example below does not, of course, include the code you would need for swapping BackGroundImage of the CheckBox to indicate CheckState. The events to "wire-up" should be obvious. Hope this is helpful.
// tested in VS 2010 Pro, .NET 4.0 FrameWork Client Profile
// uses:
// CheckBox named 'checkBox1
// ContextMenuStrip named 'contextMenuStrip1
// TextBox named 'cMenuSelectionInfo for run-time checking of results
// used to position the ContextMenuStrip
private Point cPoint;
// context click ? dubious assumption that 'right' = context click
private bool cmOpenedRight;
// the clicked ToolStripMenuItem
private ToolStripMenuItem tsMIClicked;
private void checkBox1_MouseDown(object sender, MouseEventArgs e)
{
cmOpenedRight = e.Button == MouseButtons.Right;
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
// positioning the CheckBox like this
// is something in a 'real-world' example
// you'd want to do in the Form.Load event !
// unless, of course, you'd made the CheckBox movable
if(checkBox1.Checked)
{
contextMenuStrip1.Show();
cPoint = PointToScreen(new Point(checkBox1.Left, checkBox1.Top + checkBox1.Height));
contextMenuStrip1.Location = cPoint;
}
else
{
contextMenuStrip1.Hide();
}
}
private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
// assume you do not have to check for null here ?
tsMIClicked = e.ClickedItem as ToolStripMenuItem;
tbCbMenuSelectionInfo.Text = tsMIClicked + " : " + ! (tsMIClicked.Checked);
}
private void contextMenuStrip1_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
e.Cancel = checkBox1.Checked;
}
private void contextMenuStrip1_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
if (cmOpenedRight)
{
tbCbMenuSelectionInfo.Text += " : closed because : " + e.CloseReason.ToString();
}
}
I think your approach of unchecking the check box on the context menu's closed event is a good one, what you need is a bit of "event cancelling logic"(c), like this:
private void OnContextClosing(object sender, EventArgs e)
{
_cancel = true;
cbSettings.Checked = false;
_cancel = false;
}
private void cbSettings_CheckedChanged(object sender, EventArgs e)
{
if(_cancel)
return;
if (cbSettings.Checked) {cmsSettings.Show(cbSettings, 0, cbSettings.Height);}
else {cmsSettings.Hide();}
}
This will keep your CheckChanged event from re-checking your checkbox.

Categories