I want to open a dialog as a Login-Box in my Explorer-NamespaceExtension. When I call ShowDialog() the first time the box opens but not as a modal dialog. I can click elements in the Explorer. If I close these dialog and open it again, it is a modal dialog and interaction with the Explorer isn`t possible. Thats what I want to achieve with the first open.
My idea is that I call the form first from the wrong thread. Thats the reason why I used the following code, but it doesn`t solve the problem :/
public delegate void myDelegate();
public void ShowDialogThreadSave()
{
if (this.InvokeRequired)
{
myDelegate d = new myDelegate(ShowDialogThreadSave);
this.Invoke(d);
}
else
{
this.ShowDialog();
}
}
I hope you have an idea :-)
Thanks!
Edit:
The call is fired from a background class. I have 3 possibilities to login into the extension, so i encapsulated the call:
public bool LogIn()
{
bool connected = BackEnd.isConnected();
if(loginDialog == null)
{
LogIn logIn = new LogIn();
}
else
{
if (!connected && !Utils.AlreadyLoggedIn() && !loginDialog.IsAccessible && !loginDialog.Visible)
loginDialog.ShowDialogThreadSave();
else if (!connected && !Utils.AlreadyLoggedIn() && !loginDialog.Visible)
loginDialog.ShowDialogThreadSave();
else if (!connected && !Utils.AlreadyLoggedIn() && loginDialog.Visible)
LOG.DebugFormat("error");
else
Utils.ConnectWithoutLoginWindow();
}
connected = BackEnd.isConnected();
return connected;
}
Edit2: With debugging I found out that the ShowDialogThreadSave() is always called by the UI Thread and I will never use the if... What is the problem?
Related
It has probably been covered before, but I couldn’t google anything. What is the best approach for making an iPhone-style pop-up selection menu like attached picture? I've tried with a Dialog, but I haven't found an elegant way to add the Commands so they appear nicely and both trigger the action and close the dialog at the same time. And showing a Cancel entry separately is not supported by a ComponentGroup.
See this sample:
Form hi = new Form("Pop");
Button pop = new Button("Pop");
pop.addActionListener(e -> {
Dialog dlg = new Dialog();
// makes the dialog transparent
dlg.setDialogUIID("Container");
dlg.setLayout(BoxLayout.y());
Command optionACmd = new Command("Option A");
Command optionBCmd = new Command("Option B");
Command optionCCmd = new Command("Option C");
Command cancelCmd = new Command("Cancel");
dlg.add(
ComponentGroup.enclose(
new Button(optionACmd),
new Button(optionBCmd),
new Button(optionCCmd)
)).
add(ComponentGroup.enclose(new Button(cancelCmd)));
Command result = dlg.showStretched(BorderLayout.SOUTH, true);
ToastBar.showMessage("Command " + result.getCommandName(), FontImage.MATERIAL_INFO);
});
hi.add(pop);
hi.show();
Which results in this:
Thanks Shai!
I made it into a component in case anybody has a similar need:
class MyPopupMenu extends Dialog {
private Command cancelCmd = null;
MyPopupMenu(boolean includeCancel, Command... commands) {
this(includeCancel?new Command("Cancel"):null, commands);
}
MyPopupMenu(Command cancelOptional, Command... commands) {
super();
setDialogUIID("Container");
setLayout(BoxLayout.y());
setDisposeWhenPointerOutOfBounds(true); //close if clicking outside menu
ComponentGroup group = new ComponentGroup();
for (Command cmd : commands) {
group.add(new Button(cmd));
}
add(group);
this.cancelCmd = cancelOptional;
if (cancelCmd != null) {
add(ComponentGroup.enclose(new Button(cancelCmd)));
}
/**
* show the menu and execute the selected Command,
* or do nothing if Cancel is selected
*/
public void popup() {
Command choice = showStretched(BorderLayout.SOUTH, true);
if (choice != null && choice != cancelCmd) {
choice.actionPerformed(null);
}
}
}
This is awesome, thanks guys. Any reason my buttons seem to be so small? Trying to figure out which style needs to change to increase the height. Changing the Button padding did not seem to change anything. I used the Business theme as a starting point.
As the title suggests, I want to get a mouse over event at the corners of desktop. I tried to do it by getting the position of the mouse and polling it continuously to check if it is one of the edge coordinated and then trigger the event but I think thats bad way to do it. I tried to use the library MouseKeyHook but it wasn't useful for me to generate the necessary event.
Is there any better way to get mouse over events to the corners of the screen ?
I tried to improve the code by adding the following, but for some reason the mouse over to the corners isn't triggering the action.
public async void callMainLoop() {
var slowTask = Task<Boolean>.Factory.StartNew(() => mainMethodLoop(GetMousePosition()));
await slowTask;
}
public bool mainMethodLoop(Point point) {
while (true) {
double xRes = System.Windows.SystemParameters.PrimaryScreenWidth - 1;
double yRes = System.Windows.SystemParameters.PrimaryScreenHeight - 1;
if (point.X == 0 && point.Y == 0) {
if (comboBox0.SelectedItem != null) {
executeAction(comboBox0.SelectedItem.ToString());
return true;
}
}
return false;
}
}
I am not calling this in the constructor, there ins't any freezing now.
I am calling a new xaml application with some parameter inputs using the word new, but it does not seem to be working. I am also attempting to use onclosing to set it to null. When launching it for the first time it works (everything is new), but launching it after it finished, it seems to continue its previous state (brings to finished score board). Here is the snipplet of the code . . .
quizUI = new QuizzUI.MainWindow(App.User, true);
quizUI.Closed += (o, s) =>
{
quizUI = null;
};
quizUI.LaunchQuiz(qSet);
this is hooked to a button event. does anyone know how i can absolutely new this object's state every time? the two paramters are user's info and second one is to shortcut without prompt screen/loading screen.
Here is the code for QuizzUI.MainWindow.LaunchQuizz:
public void LaunchQuiz(GameQuizzSet quiz)
{
this.Hide();
quizz = new QuizzContainer()
{
QSet = quiz,
};
if (isShortCutted)
{
bool? diag = quizz.ShowDialog();
if (diag.HasValue)
{
quizz.Close();
Close();
}
}
else
{
quizz.ShowDialog();
this.Show();
}
}
the QuizzUI.MainWindow allows the user to select their profile and which quiz to execute.
I have a pivot control and a button which does selectedIndex++ and when the selectedIndex has gone passed the last entry it will open up a messagebox asking the user if they want to quiz.
But during testing if you spam the button it will create a 0x8000ffff error when you open the MessageBox.
How do I stop this from happening? is it something to do with the ui thread being too busy or continuing to move the pivot? is the button event still running after I try to navigate out of the page?
this is what the code that does the selectedIndex++
void gotoNextQuestion()
{
if (quizPivot.SelectedIndex < App.settings.currentTest.Questions.Count() - 1)
{
//xScroll -= scrollAmount;
//moveBackground(xScroll);
if (!stoppedPaging)
{
quizPivot.SelectedIndex++;
}
//App.PlaySoundKey("next");
}
else
{
if (App.settings.testMode == App.TestModes.TrainingRecap)
{
MessageBoxResult result;
if (countAnsweredQuestions() == App.settings.currentTest.Questions.Count())
{
stoppedPaging = true;
result = MessageBox.Show("You have reviewed every training question, would you like to go back to the main menu?", "Training Over", MessageBoxButton.OKCancel);
stoppedPaging = false;
if (result == MessageBoxResult.OK)
{
positionableSpriteRadioButton.IsAnswered -= new Action<bool>(Answers_IsAnsweredCompleted);
spriteRadioButton.IsAnswered -= new Action<bool>(Answers_IsAnsweredCompleted);
App.settings.currentTest = null;
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
return;
}
}
}
else
{
MessageBoxResult result;
if (countAnsweredQuestions() == App.settings.currentTest.Questions.Count())
{
stoppedPaging = true;
result = MessageBox.Show("You have answered all of the questions, are you sure you want to finish?", "Are you sure you want to finish?", MessageBoxButton.OKCancel);
stoppedPaging = false;
}
else
{
checkFinishConditions();
}
}
quizPivot.SelectedIndex = 0;
//App.PlaySoundKey("begin");
}
App.settings.currentTest.currentQuestion = quizPivot.SelectedIndex;
}
Well, one thing is for sure
positionableSpriteRadioButton.IsAnswered -= new Action<bool>(Answers_IsAnsweredCompleted);
That isn't going to work. You're creating a new Action every time. So nothing will have the same reference id, and thus nothing will be removed.
Instead you should remove the Action<bool> and simply subscribe/unsubscribe with
positionableSpriteRadioButton.IsAnswered -= Answers_IsAnsweredCompleted;
And when you subscribe
positionableSpriteRadioButton.IsAnswered += Answers_IsAnsweredCompleted;
That way you can actually remove it again.
But I would recommend you not to use a pivot for this type of "wizard". It's abuse of the control, and going to give a really poor user experience.
Also, just because you navigate to another page, it doesn't mean the code stops running. All code in the same expression is executed, unless you add a return statement after the call to NavigationService.Navigate.
Also, always make sure that Navigation is on the UI thread by wrapping all calls to NavigationService.Navigate in a call to Dispatcher.BeginInvoke.
How could I prevent opening multiple windows from a wpf application?
I need to open a window from the menu and if I click to open it again, I want the already opened window to become active.
Any suggestions?
You could use the Application.Current.Windows collection for that. Just check whether this collection contains the window you are about to open and if it does, activate it, otherwise create new window and show it:
var existingWindow = Application.Current.Windows.Cast<Window>().SingleOrDefault(w => /* return "true" if 'w' is the window your are about to open */);
if (existingWindow != null) {
existingWindow.Activate();
}
else {
// Create and show new window
}
Here is one way to do it:
private Window _otherWindow;
private void OpenWindow()
{
if (_otherWindow == null)
{
//Pass in a reference to this window so OtherWindow can call WindowClosed when it is closed..
_otherWindow = new OtherWindow(this);
_otherWindow.Show();
}
else
_otherWindow.Activate(); //Or whatever the method is to bring a window to the front
}
public void WindowClosed()
{
_otherWindow = null;
}