In my application I have created a custom messagebox(with a different backgroud color) using a Popup. There it has a button and I have implemented the button click event.
With in the button click, it has a message box and according to "Ok" or "Cancel" it performs the operation from there onwards.
The problem is after I click the button in the popup(custom messagebox), the message box loads, but still the popup(custom messegebox) appear in the background. I need the custom popup to close entirely and to perform operations. Therefore I have used popup.IsOpen = false; as the first statement within button click, but still it appears in the background untill it finish the entire button click event. I searched for other properties, but didn't find any working.
following is the code
Popup popup = new Popup();
popup.Height = 300;
popup.Width = 480;
popup.VerticalOffset = 100;
CustomMessageBox control = new CustomMessageBox();
popup.Child = control;
popup.IsOpen = true;
this.IsEnabled = false;
control.OK_BTN.Click += (s, args) =>
{
popup.IsOpen = false;
this.IsEnabled = true;
MessageBoxResult result = MessageBox.Show("Do you want to reset the settings ?", "Settings", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
changeSettings();
}
};
Any suggestion to achieve this is highly appreciated. Thanks...!!!
The reason this happens is because all of this is happening on the UI thread which is getting blocked until you return. Until your button handler returns, no updates to the UI will happen.
If you really want the popup to disappear first, you would need to do something like
control.OK_BTN.Click += (s, args) =>
{
popup.IsOpen = false;
this.IsEnabled = true;
Dispatcher.BeginInvoke(() =>
{
MessageBoxResult result = MessageBox.Show("Do you want to reset the settings ?", "Settings", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
changeSettings();
}
});
};
That would force the MessageBox to be opened after your button handler returns. But are you sure you want the popup to disappear first? What if the user clicks cancel on the message box? Typically the message box appears directly on top of whatever invoked it and doesn't replace it.
I was just typing what Negative Eddy wrote.
Using Dispatcher.BeginInvoke will work! I tested it, works perfectly. I don't have enough rep to comment on his apparently.
Related
I am currently trying to adjust the Xamarin.Forms iOS SearchBar to show the "Cancel" button when I add text to the search bar (not through the keyboard, but a category click). I successfully did this with my code below. Now the issue is that, I want the "Cancel" button to be clickable once it shows up.
Currently I am doing the following:
Click my command that changes the Text of the searchbar -> works
Cancel button shows up -> works
Cancel button is clickable -> does not work. it is gray. I need to click the searchbar (so the keyboard shows up) to have it turn blue and clickable.
This is my code:
[assembly: ExportRenderer(typeof(CustomSearchBar), typeof(SearchBar_iOS))]
namespace Project.iOS.Renderers
{
public class SearchBar_iOS : SearchBarRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.SearchBar> e)
{
base.OnElementChanged(e);
var element = e.NewElement as CustomSearchBar;
if (Control != null && element != null)
{
this.Control.TextChanged += (s, ea) =>
{
//if (ea.SearchText == "")
this.Control.ShowsCancelButton = true;
};
this.Control.OnEditingStarted += (s, ea) => //when control receives focus
{
this.Control.ShowsCancelButton = true;
};
this.Control.OnEditingStopped += (s, ea) => //when control looses focus
{
this.Control.ShowsCancelButton = false;
};
Control.BackgroundColor = Color.Transparent.ToUIColor();
Control.Layer.CornerRadius = 10;
Control.ClipsToBounds = true;
Control.SearchBarStyle = UISearchBarStyle.Minimal;
}
}
Is there a call in my renderer that can force it to be clickable when text is added?
This was already discussed for iOS native here:
How do you keep the cancel button in the search bar enabled when the keyboard is dismissed?
However it appears that iOS does not want you messing with the behavior of the Cancel button otherwise they would have exposed it publicly. That said, try this in your custom renderer for the OnEditingStopped event (quick test on my end worked):
this.Control.OnEditingStopped += async (s, ea) => //when control looses focus
{
this.Control.ShowsCancelButton = false;
var searchBar = this.Control;
BeginInvokeOnMainThread(() =>
{
var cancelButton = searchBar.ValueForKey(new NSString("cancelButton")) as UIButton;
cancelButton.Enabled = true;
});
};
There is a risk of Apple rejection or other undiscovered issues, so don't yell at me if it does not work. :-)
Also, since the cancel button is not made publicly accessible with out getting to it via the ValueForKey method, Apple could change the key name at any time which would break this hacky workaround.
If the user clicks on a button, a dialog shows up, asking to input a string, and there's an 'OK' button on the same dialog, when the user presses that, the dialog should close. That's at least the plan, the problem is: after adding the eventhandler to the OK button, my application freezes, when the user would open the dialog.
addNewFamButton = FindViewById<Button>(Resource.Id.newFamilyButton);
addNewFamButton.Click += (sender, e) => {
Dialog dialog = new Dialog(this);
dialog.SetContentView(Resource.Layout.addNewFamily);
dialog.SetTitle("Add new family to the list");
dialog.Show();
// Problem starts here:
Button saveNewFamily = FindViewById<Button>(Resource.Id.dialogButtonOK);
saveNewFamily.Click += (object o, EventArgs ea) => { dialog.Dispose(); };
};
I tried it with dialog.Cancel() too, but I got the same results. If I remove the last two lines, the dialog works, but obviously won't close.
FIXED: Thanks to user370305 for the simple solution:
Button saveNewFamily = dialog.FindViewById<Button>(Resource.Id.dialogButtonOK);
Your OK button is part of Dialog view, so you have to find that view using your dialog object reference, something like, (I am not familiar with xamarin but this one gives you hint)
Change your line,
// Problem starts here:
Button saveNewFamily = FindViewById<Button>(Resource.Id.dialogButtonOK);
with
Button saveNewFamily = dialog.FindViewById<Button>(Resource.Id.dialogButtonOK);
try this
// create an EditText for the dialog
final EditText enteredText = new EditText(this);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Title of the dialog");
builder.setView(enteredText);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int id)
{
// perform any operation you want
enteredText.getText().toString());// get the text
// other operations
dialog.cancel(); // close the dialog
}
});
builder.create().show();
I'm working on a C# WinForms application in which I have a number of processes that are all managed by a 'master' application.
In this master application, each process is visualized by its own FlowLayoutPanel which contains a number of buttons for various function. I call these panels the 'process blocks'.
However, when many of these processes are made, not all blocks easily fit on the screen. For this reason I am implementing a 'compact mode', which hides all the buttons of all the process blocks, leaving only their name, their status and the start/stop button visible. I then assign a ContextMenuStrip to each process block, in which I show all the buttons listed as a ToolStripMenuItem so I can access all the functions of the process block that way. I am clearing these ContextMenuStrips dynamically and add the items when the menu is opened.
I do this by iterating over all the child controls of the FlowLayoutPanel, see if they are of type Button, and if so, I add them to the ContextMenuStrip. See the code snippet below:
private void PanelCmsOpened(object sender, EventArgs e) {
try {
ContextMenuStrip cMenuStrip = (ContextMenuStrip) sender;
// Clear all items from the context menu
cMenuStrip.Items.Clear();
// Loop over all controls in the FlowLayoutPanel
foreach (var c in CPanel.Controls) {
Button btn = c as Button;
if (btn == null) continue; // Not a button, continue
// Get the text from the button
string lbl = btn.Text;
if (string.IsNullOrEmpty(lbl)) {
try {
// The button has no text (only an icon), so we get the tooltip text of the button
lbl = PanelTooltip.GetToolTip(btn);
}
catch {
// We can't get any text to display, so skip this button
continue;
}
}
// Add a new item to the ContextMenuStrip
cMenuStrip.Items.Add(new ToolStripMenuItem(lbl,
btn.BackgroundImage,
(s, ea) => btn.PerformClick() // Perform a click on the button
)
{
Enabled = btn.Enabled
});
}
}
catch (Exception Ex) {
MessageBox.Show("Fout bij openen van context menu: " + Ex.Message, "Fout", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
The problem:
Now this is all working fine, as long as the buttons are visible. However, when going to compact mode, I hide the buttons by setting their Button.Visible property. In that case, nothing happens. I've tried putting a try-catch block around the PerformClick, but no exception is thrown. Just nothing happens. Does anyone know how to make this work for hidden buttons?
PerformClick checks if button available for clicking before performing click. Hidden buttons are considered unavailable. You can simply show button just before performing click, and hide it after clicking:
cMenuStrip.Items.Add(
new ToolStripMenuItem(lbl, btn.BackgroundImage, (s, ea) => {
var size = btn.Size;
btn.Size = Size.Empty; // button still will be invisible
btn.Show(); // make it clickable
btn.PerformClick();
btn.Hide(); // hide again
btn.Size = size; // restore original size
});
NOTE: If you also need to add some visible buttons, then you should handle them separately to avoid flickering
cMenuStrip.Items.Add(new ToolStripMenuItem(
lbl, btn.BackgroundImage, (s, ea) => ClickButton(btn)));
Where ClickButton is a method which performs different logic depending whether button is visible or not:
private void ClickButton(Button button)
{
if (button.Visible)
{
button.PerformClick();
return;
}
var size = button.Size;
button.Size = Size.Empty;
button.Show();
button.PerformClick();
button.Hide();
button.Size = size;
}
The only thing you can't do is setting visible = false;
Other than that yu can use any trick to hide the buttons: You can stack them behind another control, you can move them out of sight in any direction or even move them into a different parent:
To hide them:
panel1.Size = Size.Empty;
button1.Parent = panel1;
//..
To show them again:
button1.Parent = this;
//..
Assuming they sit on the Form.
Note that they will have kept their original locations and sizes; watch for changes in the tab-order and z-order!
If the button is not visible the Click event won't be raised.
One option is to take the code which is in the button click event and add it as a separate method. Then call the method instead of the PerformClick row. This will work though if you do identical things on every button click.
Another options it to make the buttons transparent. This will make them invisible to the client and the PerformClick event will work fine. You can see that in the following link :Drawing a transparent button.
Hope this helps.
I want to create a dialog requesting user information, and I set the Ok button's DialogResult to OK. In the OK button's Click event, the program checks for empty textboxes, and if there are empty textboxes, the program shows a message box and stops the dialog box from closing. But because I set the DialogResult to OK, there are no way of stopping the box from closing. Could you give me some solutions? Thanks.
Here's my code:
outcomeName = outcomeNameTxtBx.Text;
outcomeDetails = outcomeDetailsTxtBx.Text;
addTargetedClasses();
finishDate = finishDatePicker.Value;
beginWorkingDate = beginWorkingDatePicker.Value;
if (!isAllInfoEntered())
{
//Show the message box
return;
}
Just set it back if you are not happy:
if (!isAllInfoEntered())
{
this.DialogResult = DialogResult.None;
//Show the message box
return;
}
Don't make return:
if (!isAllInfoEntered())
{
this.DialogResult = DialogResult.None;
//Show the message box
}
else
{
return;
}
This form has a NotifyIcon object. When the user clicks on the Close button, I want the form not to close but to become invisible. And then, if the user wants to see the form again, he can double click on the icon in the systray. If the user wants to close the form, he can right click on the icon and select "close".
Can someone tell me how to make the close button not close the form but make it invisible?
(or if someone can think of a better way to achieve the same objective by all means)
First, you want to handle your Main form's .FormClosing event (or by overriding the OnFormClosing method). Cancel that by setting e.Cancel to true.
Then, you use a NotifyIcon to add an icon to the system tray.
Finally, hide the form by calling .Hide().
protected override void OnFormClosing(FormClosingEventArgs e) {
if (IActuallyWantToCloseFlag)
return;
var ni = new NotifyIcon(this.components)
{
Icon = someIcon,
Text = "My text",
Visible = true
};
ni.DoubleClick += (sender, args) => { this.Show(); };
this.Hide();
e.Cancel = true;
}
This should get you started. You probably want to make ni a member variable, so that you can continue to hide/show the icon as you show/hide your form.
You could try making it a tray icon app. There's a good tutorial here for that: http://www.developer.com/net/net/article.php/3336751/C-Tip-Placing-Your-C-Application-in-the-System-Tray.htm
The simplest way to achieve what you want would be to subscribe to the FormClosing event and set visible false, by including this sort of code:
FormClosing += (sender, args) => { args.Cancel = true; Visible = false; };