2009-08-13 8 views
14

Das ChildWindow ist ein modales Fenster, aber es blockiert nicht. Gibt es eine Möglichkeit, es zu blockieren? Ich möchte im Grunde eine ShowDialog() -Methode, die ChildWindow.Show() aufrufen, aber nicht zurückgeben, bis der Benutzer das ChildWindow geschlossen hat. Ich habe versucht, mit Monitor.Enter() nach ChildWindow.Show() zu blockieren, aber das ChildWindow nie gerendert und der Browser einfach aufgehängt. Hat jemand Ideen?Wie ChildWindow blockiert

+0

Können Sie uns erklären, was Sie versuchen zu erreichen, ? – Ray

+0

Nur ein einfaches modales Blockierungsfenster ähnlich MessageBox.Show() oder Form.ShowDialog() –

+0

Ich habe alles versucht und ich habe nie eine Lösung gefunden. Ich habe versucht, meine eigene MessageBox zu erstellen.Ich habe es sogar asynchron versucht, aber es war immer verschlossen. Ich habe aufgegeben, nachdem ich gelesen habe, dass Tim Heuer sagt, dass es nicht möglich ist, echtes Modal zu haben. – Paully

Antwort

5

Sie können nicht tun, was Sie in Silverlight zu tun versuchen. Alle Änderungen, die Sie an der Benutzeroberfläche vornehmen, werden im Benutzeroberflächenthread ausgeführt. Wenn Sie den UI-Thread blockieren, kann der Benutzer nicht mit dem Browser interagieren. Daher können Sie den Thread nicht entsperren.

Wenn Sie wirklich ein Sperrdialogfenster erstellen möchten, ist der einzige Weg, das zu tun, ist aus einem nicht-UI-Thread. Z.B. wird nicht zurückkehren

private void ShowModalDialog() 
    { 
     AutoResetEvent waitHandle = new AutoResetEvent(false); 
     Dispatcher.BeginInvoke(() => 
     { 
      ChildWindow cw = new ChildWindow(); 
      cw.Content = "Modal Dialog"; 
      cw.Closed += (s, e) => waitHandle.Set(); 
      cw.Show(); 
     }); 
     waitHandle.WaitOne(); 
    } 

Diese Methode ein Dialogfenster erscheint und bis wird das Dialogfenster geschlossen: Sie könnte ein Verfahren, das sieht etwas schaffen wie. Diese Methode kann aber nur von einem Nicht-UI-Thread aufgerufen werden. Der Aufruf aus dem UI-Thread führt zu einem Deadlock (da der UI-Thread auf ein Ereignis wartet, das nur auf dem UI-Thread ausgelöst werden kann).

Alternativ sollten Sie Ihre Logik async machen eher überlegen, als es zwingt synchron zu sein.

+0

Ich mag diese Lösung und es sieht so aus, als ob sie funktionieren sollte, aber da sie nicht auf dem UInthread aufgerufen werden kann, bin ich mir nicht sicher, ob ich das verwenden kann (obwohl ich dies in meiner Frage nicht angegeben habe Ich habe nicht einmal darüber nachgedacht, dann)). So oder so, große Problemumgehung. –

-1

Ich gehackt bei der Erstellung eines "blockierenden" modalen Dialogfelds, indem Sie ein benutzerdefiniertes Steuerelement, das eine vertikale und horizontale Ausrichtung als Dehnung hat, und fügen Sie dann als Kind des Layouts des aktuellen Steuerelements.

z.B.

<Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> 
     <Rectangle Fill="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="0.3" /> 
    </Grid> 

und dann in das benutzerdefinierte Steuerelement

Utilities.UITools.MessageBox x = new Utilities.UITools.MessageBox(); 
x.SetError(e.Result); 
this.LayoutRoot.Children.Add(x); 

Je nachdem, was in der modal angezeigt werden muss, ich dynamisch Kontrollen an den modalen Layout hinzuzufügen. Klar, keine elegante Lösung, aber zumindest funktioniert es.

+0

Das würde es in gewisser Weise modal machen, aber es scheint nicht, dass es blockieren würde, da es keinen Funktionsaufruf gibt, der blockieren würde, bis der Benutzer das Nachrichtenfeld schließt. –

+0

Ich blockierte es, indem ich ein Ereignis in das Nachrichtenfeld eingab. Daher blockiert es den Rest des Programms, bis das Ereignis ausgelöst wird – Johannes

3

Wenn Sie eine Aktion auf Ihrem Kind Fenster schließen ausführen möchten, verwenden Sie den folgenden Code ein. Ausblenden vor unerwünschten Kontrollen aufrufen und zeigen auf der Nähe des Kindes Fenster, einfach :)

ChildWindow cw = new ChildWindow(); 
cw.Closed += new EventHandler(cw_Closed); 
cw.Show(); 
0

Sie könnten versuchen, immer die enge Ereignis abbrechen und die Dialog später einstellen.

void ConfigTemplatePopup_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
    { 
     if (tmpDialogResult != null || DialogResult == true) return; 
     tmpDialogResult = DialogResult; //this is a field 
     e.Cancel = true; 
     var myMessageBox = new WspMessageBox("Are you sure you want to close?", true); 
     myMessageBox.Closed += (s, e2) => 
            { 
             if (wspMessageBox.DialogResult == true) 
             { 
              DialogResult = tmpDialogResult; 
             }else 
             { 
              tmpDialogResult = null; 
             } 
            }; 
     myMessageBox.Show(); 
    } 
0

async and await in Silverlight 5 Verwenden Sie können leicht eine statische Show-Methode erstellen, die blockiert werden können, wie

public partial class MyDialog { 
    MyResultType result; 
    readonly AutoResetEvent waitHandle; 

    MyDialog() { 
    InitializeComponent(); 
    waitHandle = new AutoResetEvent(false); 
    } 

    public static Task<MyResultType> Show() { 
    var dialog = new MyDialog(); 
    dialog.Show(); 
    dialog.Closed += (s, e) => dialog.waitHandle.Set(); 
    return Task<MyResultType>.Factory.StartNew(() => { 
     dialog.waitHandle.WaitOne(); return dialog.result; }); 
    } 

    void OkButton_Click(object sender, RoutedEventArgs e) { 
     result = new MyResultType(); 
     // Initialize result... 

     Close(); 
    } 
} 

und rufen Sie den Dialog wie

public async void TestDialog() { 
    var result = await ConfirmBox.Show(); 

    // This code will be performed after the Dialog is closed. 
    // use result... 
} 
+0

-1 Ich fürchte, weil dieses Snippet nicht kompiliert. Die Ausgabe von 'Task .Factory.StartNew()' ist nicht abzusehen. Während diese Antwort das async/await-Muster in den Mix einführt, löst es nicht das grundlegende Problem, dass Sie den UI-Thread nicht blockieren können, ohne den Browser einzufrieren. Daher bietet dieser Ansatz keinen echten Mehrwert über die Lösung von Keith Mahoney hinaus. –

+0

Dieses Snippet stammt von meinem Arbeitsprojekt. Ich benutze es als eine gemeinsame Lösung für Dialoge. Um es zu kompilieren, benötigen Sie das "async targeting pack", das Sie mit dem nuget zu Ihrem Projekt hinzufügen können. Bitte lesen Sie den Artikel über den Link in meiner Antwort. –