Problembehandlung bei Ladefehlern im WPF- und Silverlight-Designer
Der WPF Designer für Visual Studio enthält einen anspruchsvollen und erweiterbaren visuellen Designer, der XAML rendert. Wenn die XAML-Datei im Designer nicht geladen wird, haben Sie mehrere Möglichkeiten, herauszufinden, wo der Fehler liegt. In diesem Thema werden einige Tipps und Techniken beschrieben, die Ihnen bei der Problembehandlung von WPF-Designer-Ladefehlern helfen. Die Beispiele in diesem Thema beziehen sich vorrangig auf WPF, aber die meisten der Probleme, Techniken und Lösungen gelten für WPF und Silverlight.
Tipp
Viele der Techniken in diesem Thema gelten auch für Expression Blend.
Debuggen eines Ladefehlers
Verwenden Sie den Visual Studio-Debugger, um den Code zur Entwurfszeit schrittweise auszuführen. Sie können Ladefehler mithilfe einer zweiten Instanz von Visual Studio debuggen. Weitere Informationen finden Sie unter Gewusst wie: Debuggen eines Designerladefehlers.
Schritte zur Fehlerbehebung
Die folgenden Schritte helfen Ihnen bei der Fehlerbehandlung von WPF-Designer-Ladefehlern.
Lesen Sie die Ausnahmemeldungen, die angezeigt werden.
Dies scheint zwar auf der Hand zu liegen, aber es ist wichtig, dass Sie bei Ausnahmen die Meldung sorgfältig lesen. Manchmal kann so das Problem schnell erkannt werden. Weitere Informationen finden Sie unter Debuggen und Interpretieren von Fehlern im WPF-Designer.
Stellen Sie fest, ob das Problem von der Implementierung verursacht wird.
Erstellen Sie die Anwendung, und führen Sie sie aus, um festzustellen, ob das Problem nur von der Implementierung verursacht wird oder ob eine Interaktion mit dem WPF-Designer die Ursache sein könnte. Wenn sich die Anwendung erstellen und ausführen lässt, wird der Entwurfszeitfehler wahrscheinlich von der Implementierung verursacht.
Stellen Sie fest, ob das Problem ein während des Ladevorgangs auftretender Fehler ist.
Wenn die Entwurfsansicht aufgrund einer Ausnahme nicht geladen wird, handelt es sich wahrscheinlich um einen Ladefehler. Wenn Sie benutzerdefinierten Code verwenden, der zur Entwurfszeit geladen wird, und Ausnahmen oder Ladefehler zur Entwurfszeit auftreten, finden Sie weitere Informationen im Abschnitt Schreiben von Code für die Entwurfszeit in diesem Thema.
Überprüfen Sie den Code, der zur Entwurfszeit geladen wird.
Es gibt zwei Möglichkeiten, Code zu schreiben, der auch zur Entwurfszeit ausgeführt wird. Die erste Möglichkeit besteht darin, defensiven Code zu schreiben, indem Sie die Eingabeparameter für Klassen überprüfen. Bei der zweiten Möglichkeit überprüfen Sie, ob der Entwurfsmodus aktiv ist, indem Sie die GetIsInDesignMode-Methode aufrufen. Weitere Informationen finden Sie im Abschnitt Schreiben von Code für die Entwurfszeit in diesem Thema.
Überprüfen Sie andere Bereiche im Code.
Im Abschnitt Programmiertipps dieses Themas finden Sie verschiedene Programmiertipps für die Arbeit mit dem WPF-Designer. Informationen zum Schreiben von robusterem Code finden Sie im Abschnitt Empfohlene Vorgehensweisen für die Programmierung in diesem Thema.
Wenn die Probleme weiterhin bestehen, können Sie sich im WPF-Designer-Forum auf MSN mit anderen Entwicklern austauschen, die den WPF-Designer verwenden. Wenn Sie potenzielle Probleme melden oder Vorschläge machen möchten, verwenden Sie die Feedback-Website für Visual Studio und .NET Framework.
Schreiben von Code für die Entwurfszeit
Vergewissern Sie sich, dass der Code sowohl zur Entwurfszeit als auch zur Laufzeit ausgeführt wird. Wenn der Code zur Entwurfszeit ausgeführt wird, gehen Sie nicht davon aus, dass Application.Current die Anwendung ist. Wenn Sie z. B. Expression Blend verwenden, ist Current Expression Blend. Zur Entwurfszeit ist MainWindow nicht das Hauptfenster der Anwendung. Im Folgenden finden Sie typische Operationen, die bewirken, dass ein benutzerdefiniertes Steuerelement zur Entwurfszeit nicht funktioniert.
Umwandeln von Current in die benutzerdefinierte Unterklasse von Application
Umwandeln von MainWindow in die benutzerdefinierte Unterklasse von Window
Verwenden der FindResource-Methode oder der FindName-Methode für Current oder MainWindow
Keine Überprüfung, ob Application.Current oder Application.MainWindow einen Wert zurückgegeben hat, der null ist. Wenn Visual Studio kein Anwendungsobjekt erstellt, dann gibt Application.Current möglicherweise null zurück.
Keine Überprüfung, ob Assembly.GetEntryAssembly einen Wert zurückgegeben hat, der null ist. Für Visual Studio gibt diese Methode nie null zurück.
Es gibt zwei Möglichkeiten, den Code für die Entwurfszeit zu schreiben. Der erste Ansatz besteht darin, defensiven Code zu schreiben, indem die Eingabeparameter für Klassen überprüft werden, beispielsweise Wertkonverter. Bei der zweiten Möglichkeit überprüfen Sie, ob der Entwurfsmodus aktiv ist, indem Sie die GetIsInDesignMode-Methode aufrufen. Verwenden Sie für Silverlight die IsInDesignTool-Eigenschaft.
Das Überprüfen der Eingabeparameter ist für einige Implementierungen notwendig, da die Entwicklungsumgebung für einige Eingaben andere Typen bereitstellt als die von der Laufzeitumgebung bereitgestellten Typen.
Stilselektoren und Wertkonverter erfordern normalerweise einen dieser Ansätze, damit sie zur Entwurfszeit ordnungsgemäß ausgeführt werden.
Wertkonverter
Die benutzerdefinierten IValueConverter-Implementierungen sollten eine Überprüfung auf null und auf den im ersten Parameter der Convert-Methode erwarteten Typ durchführen. Der folgende XAML-Code zeigt eine Bindung an Application.Current, die zur Entwurfszeit fehlschlägt, wenn der Wertkonverter nicht ordnungsgemäß implementiert wird.
<ComboBox.IsEnabled>
<MultiBinding Converter="{StaticResource specialFeaturesConverter}">
<Binding Path="CurrentUser.Rating" Source="{x:Static Application.Current}"/>
<Binding Path="CurrentUser.MemberSince" Source="{x:Static Application.Current}"/>
</MultiBinding>
</ComboBox.IsEnabled>
Die Bindung löst eine Ausnahme zur Entwurfszeit aus, da Application.Current auf die Designer-Anwendung statt auf Ihre Anwendung verweist. Um die Ausnahme zu verhindern, muss der Wertkonverter seine Eingabeparameter überprüfen oder überprüfen, ob der Entwurfsmodus aktiv ist.
Im folgenden Codebeispiel wird gezeigt, wie Eingabeparameter in einem Wertkonverter überprüft werden, der true zurückgibt, wenn zwei Eingabeparameter die Bedingungen einer bestimmten Geschäftslogik erfüllen.
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Check the values array for correct parameters.
// Designers may send null or unexpected values.
if (values == null || values.Length < 2) return false;
if (!(values[0] is int)) return false;
if (!(values[1] is DateTime)) return false;
int rating = (int)values[0];
DateTime date = (DateTime)values[1];
// If the user has a good rating (10+) and has been a member for
// more than a year, special features are available.
if((rating >= 10) &&
(date.Date < (DateTime.Now.Date - new TimeSpan(365, 0, 0, 0))))
{
return true;
}
return false;
}
Beim zweiten Ansatz für das Schreiben von Code für die Entwurfszeit wird überprüft, ob der Entwurfsmodus aktiv ist. Im folgenden Codebeispiel wird statt der vorher gezeigten Parameterprüfung eine Entwurfsmodusprüfung veranschaulicht.
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Check for design mode.
if ((bool)(DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue))
{
return false;
}
int rating = (int)values[0];
DateTime date = (DateTime)values[1];
// If the user has a good rating (10+) and has been a member for
// more than a year, special features are available.
if((rating >= 10) &&
(date.Date < (DateTime.Now.Date - new TimeSpan(365, 0, 0, 0))))
{
return true;
}
return false;
}
Stilselektoren
Auch die benutzerdefinierten Stilselektoren müssen so implementiert werden, dass sie im Entwurfsmodus ausgeführt werden können. Der folgende XAML-Code zeigt einen Selektor für eine benutzerdefinierte Vorlage, der Application.MainWindow zur Laufzeit verwendet, um festzustellen, welche Ressource als eine DataTemplate zurückgegeben wird. Zur Entwurfszeit ist diese Ressource unter Umständen nicht verfügbar, sodass die überschriebene SelectTemplate-Funktion null zur Entwurfszeit zurückgibt.
<local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>
<ListBox Width="400" Margin="10"
ItemsSource="{Binding Source={StaticResource myTodoList}}"
ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
HorizontalContentAlignment="Stretch"
IsSynchronizedWithCurrentItem="True"/>
Im folgenden Code wird die Implementierung des Stilselektors veranschaulicht.
public class TaskListDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(
object item,
DependencyObject container)
{
if (item != null && item is Task)
{
Task taskitem = item as Task;
Window window = Application.Current.MainWindow;
// To run in design mode, either test for the correct window class
// or test for design mode.
if (window.GetType() == typeof(MainWindow))
// Or check for design mode:
//if (!DesignerProperties.GetIsInDesignMode(window))
{
if (taskitem.Priority == 1)
return window.FindResource("importantTaskTemplate") as DataTemplate;
else
return window.FindResource("myTaskTemplate") as DataTemplate;
}
}
return null;
}
}
Programmiertipps
Im Folgenden finden Sie einige Programmiertipps für die Arbeit mit dem WPF-Designer.
Wenn Sie möchten, dass das benutzerdefinierte Steuerelement im WPF-Designer geladen wird, müssen Sie get- und set-Methoden der CLR für alle von Ihnen definierten Abhängigkeitseigenschaften bereitstellen. Weitere Informationen finden Sie unter Benutzerdefinierte Abhängigkeitseigenschaften.
Adorner des Typs ComboBox werden nicht unterstützt.
Wenn Sie ein Windows Forms-Steuerelement eines Drittanbieters verwenden möchten, erstellen Sie einen UserControl-Typ, der in seiner Controls-Auflistung eine Instanz des Steuerelements des Drittanbieters hat. Weitere Informationen finden Sie unter Exemplarische Vorgehensweise: Hosten eines Windows Forms-Steuerelements eines Drittanbieters in einer WPF-Anwendung.
Die Entwurfszeit für das FlowDocument wird nicht direkt unterstützt. Wenn Sie den WPF-Designer in einem eingebetteten FlowDocument verwenden möchten, müssen Sie das FlowDocument zunächst in einem Frame-Steuerelement platzieren, welches Sie dann im WPF-Designer verwenden können.
Empfohlene Vorgehensweisen für die Programmierung
Im Folgenden finden Sie einige empfohlene Vorgehensweisen für die Programmierung, in denen gezeigt wird, wie Sie robusteren Code für den WPF-Designer schreiben.
Umschließen Sie Bearbeitungsbereiche immer mit using-Anweisungen oder try/finally-Blöcke. Wenn eine Ausnahme ausgelöst wird, wird die Änderung im Dispose-Aufruf abgebrochen. Weitere Informationen finden Sie unter ModelEditingScope.
Verschieben Sie ein Steuerelement mithilfe eines ModelEditingScope von einem Container in einen anderen. Wird dies nicht ausgeführt, wird eine Ausnahme ausgelöst.
Legen Sie in WPF und im WPF-Designer einen Eigenschaftswert nicht auf seinen Standardwert fest, wenn Sie planen, ihn zu löschen. Rufen Sie für NaN-Werte, z. B. Height, die ClearValue-Methode auf, statt NaN zuzuweisen.
Wenn Sie Werte von einer Eigenschaft abrufen, verwenden Sie den berechneten Wert der Eigenschaft. Sie sollten also die ComputedValue-Eigenschaft statt der GetCurrentValue-Methode von ModelItem verwenden. Die GetCurrentValue-Methode gibt Bindungen und andere Ausdrücke zurück, wenn sie im XAML-Code gespeichert waren, sodass Sie in manchen Fällen Umwandlungsausnahmen erhalten.
Siehe auch
Konzepte
Weitere Ressourcen
Gewusst wie: Debuggen eines Designerladefehlers