Problembehandlung bei Ladefehlern im WPF Designer
Aktualisiert: November 2007
Der Windows Presentation Foundation (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.
Hinweis: |
---|
Viele der Techniken in diesem Thema gelten auch für Expression Blend. |
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.
Verwenden Sie den Visual Studio-Debugger, um den Code zur Entwurfszeit schrittweise auszuführen. Weitere Informationen finden Sie unter Exemplarische Vorgehensweise: Debuggen von benutzerdefinierten WPF-Steuerelementen zur Entwurfszeit.
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. Wenn Sie mit Ressourcen arbeiten, die nicht geladen werden, lesen Sie den Abschnitt UserControl und benutzerdefinierte Steuerelementressourcen zur 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
Verweisen auf Ressourcen von Application.Resources. Die Entwurfszeitinstanz von Application entspricht nicht der Anwendung und besitzt nicht dieselben Ressourcen.
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. Beim zweiten Ansatz wird durch Aufrufen der GetIsInDesignMode-Methode überprüft, ob der Entwurfsmodus aktiv ist.
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(Window1))
// 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;
}
}
Ressourcen von Benutzersteuerelementen und benutzerdefinierten Steuerelementen zur Entwurfszeit
Standardmäßig stehen Ressourcen für UserControl-Elemente und benutzerdefinierte Steuerelemente, die zur Laufzeit verfügbar sind, möglicherweise zur Entwurfszeit nicht zur Verfügung. Wenn Sie die benutzerdefinierten Steuerelemente und Benutzersteuerelemente zu einer Page oder einem Window auf der Entwurfsoberfläche hinzufügen, wird eine Instanz des Steuerelements erstellt. Ressourcen in App.xaml sind für UserControl-Instanzen und benutzerdefinierte Steuerelementinstanzen, die auf einer Seite oder in einem Fenster geladen werden, nicht verfügbar.
Wenn Sie die Ressourcen zur Entwurfszeit verfügbar machen möchten, ordnen Sie sie einem separaten Ressourcenwörterbuch zu, und schließen Sie das Wörterbuch in App.xaml und im XAML-Code des Steuerelements ein. Machen Sie alle StaticResource-Verweise zu DynamicResource-Verweisen. Im folgenden Codebeispiel wird veranschaulicht, wie Sie ein Ressourcenwörterbuch freigeben, sodass die darin enthaltenen Ressourcen zur Entwurfszeit verfügbar sind.
UserControl1.xaml
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Paket-URI-Syntax
Sie sollten keine anwendungsrelativen Ressourcenverweise verwenden. Im folgenden Codebeispiel wird die anwendungsbasierte Syntax veranschaulicht, die möglicherweise zur Entwurfszeit fehlschlägt.
<Image Name="image1" Source="pack://application:,,,/Image1.bmp" />
Solche Verweise sind nicht zur DLL, sondern zur Anwendung relativ. Wenn Sie in einer DLL einen anwendungsrelativen Ressourcenverweis verwenden, ist die DLL von Ressourcen in der übergeordneten Anwendung abhängig. Dieser Ansatz ist instabil und funktioniert möglicherweise zur Entwurfszeit nicht.
Statt anwendungsrelative Ressourcenverweise zu verwenden, fügen Sie Ressourcen direkt der DLL hinzu und verwenden komponentenbasierte Ressourcenverweise. Weitere Informationen finden Sie unter Paket-URIs in Windows Presentation Foundation.
In den folgenden Codebeispielen wird die komponentenbasierte Syntax veranschaulicht, die die empfohlene Vorgehensweise darstellt.
<Image Name="image1" Source="/TestHostApp;component/Image1.bmp" />
<Image Name="image1" Source="pack://application:,,,/TestHostApp;component/Image1
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.
Binden Sie Bearbeitungsbereiche immer in using-Anweisungen oder try/finally-Blöcke ein. 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 Eigenschaftenwert 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
Weitere Ressourcen
Debuggen und Interpretieren von Fehlern im WPF-Designer