Welche Ansätze stehen für Dummy-Entwurfszeitdaten in WPF zur Verfügung?

97

Ich arbeite ohne Ausdrucksmischung und verwende nur den XAML-Editor in vs2010. Abgesehen von dieser Weisheit sehe ich zunehmend einen Bedarf an Datenbindung zur Entwurfszeit. In einfachen Fällen FallbackValuefunktioniert die Eigenschaft sehr gut (Textboxes und TextBlocks usw.). Vor allem beim Umgang mit ItemsControlund dergleichen müssen Beispieldaten im Designer sichtbar sein, damit Sie Steuerelemente und Datenvorlagen anpassen und optimieren können, ohne die ausführbare Datei ausführen zu müssen.

ich weiß das ObjectDataProvider die Bindung an einen Typ ermöglicht und somit Entwurfszeitdaten für die Visualisierung bereitstellen kann, aber dann gibt es einige Jonglagen, damit die realen Laufzeitdaten gebunden werden können, ohne Ressourcen zu verschwenden, indem beide Entwurfszeiten geladen werden. Dummy-Daten und die Laufzeitbindungen.

Was ich wirklich will, ist die Fähigkeit, beispielsweise "John", "Paul", "George" und "Ringo" im XAML-Designer als stilvolle Elemente in meinem zu haben ItemsControl , aber echte Daten bei der Anwendung läuft.

Ich weiß auch, dass Blend einige ausgefallene Attribute zulässt, die Entwurfszeitbindungsdaten definieren, die von WPF unter Laufzeitbedingungen effektiv ignoriert werden.

Meine Fragen sind also:

1. Wie kann ich Entwurfszeitbindungen von Sammlungen und nicht trivialen Daten im Visual Studio XAML-Designer nutzen und dann reibungslos zu Laufzeitbindungen wechseln?

2. Wie haben andere dieses Problem zwischen Entwurfszeit und Laufzeitdaten gelöst? In meinem Fall kann ich nicht sehr einfach dieselben Daten für beide verwenden (wie man es beispielsweise mit einer Datenbankabfrage tun könnte).

3. Sind ihre Alternativen zur Ausdrucksmischung, die ich für das datenintegrierte XAML-Design verwenden könnte? (Ich weiß, dass es einige Alternativen gibt, aber ich möchte speziell etwas, das ich verwenden und gebundene Beispieldaten usw. sehen kann?)

el2iot2
quelle

Antworten:

120

Mit VS2010 können Sie Design-Time-Attribute verwenden (funktioniert sowohl für SL als auch für WPF). Normalerweise habe ich sowieso eine Scheindatenquelle, also ist es nur eine Frage von:

  • Hinzufügen der Namespace-Deklaration

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  • Hinzufügen des Scheindatenkontexts zu Fenster- / Steuerungsressourcen

    <UserControl.Resources>
      <ViewModels:MockXViewModel x:Key="DesignViewModel"/>
    </UserControl.Resources>
  • Festlegen des Datenkontexts für die Entwurfszeit

    <Grid d:DataContext="{Binding Source={StaticResource DesignViewModel}}" ...

Funktioniert gut genug.

Goran
quelle
2
Wenn Sie Probleme bei der Verwendung haben d:DataContext, finden Sie möglicherweise Hilfe in dieser Frage: stackoverflow.com/questions/8303803/…
Martin Liversage
27
Würde dieses Beispiel nicht dazu führen, dass eine Instanz von MockXViewModel für einen Release-Build in Ihre Ressourcen geladen wird? Ist das nicht ein Problem?
Jpierson
12
Zu Ihrer Information: Sie benötigen außerdem Folgendes, oder der VS2012-Compiler kompiliert die xaml-Datei nicht: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"undmc:Ignorable="d"
Orion Edwards
51
jpierson hat recht. Ich benutze lieber <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" .... Auf diese Weise wird das verspottete Ansichtsmodell nur im Designer erstellt, nicht während der Ausführung Ihrer Anwendung. Beachten Sie, dass für diesen Ansatz Ihr Mock-View-Modell einen parameterlosen Konstruktor haben muss. Gleiches gilt jedoch für das oben in der Antwort angegebene Beispiel.
René
2
@ René dein Ansatz ist viel besser. Bitte fügen Sie es als Antwort hinzu und ich werde dafür stimmen
dss539
15

Als Amalgam von Gorans akzeptierter Antwort und Renes ausgezeichnetem Kommentar.

  • Fügen Sie die Namespace-Deklaration hinzu. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

  • Verweisen Sie auf Ihren Entwurfszeitdatenkontext aus dem Code.
    <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" ...

John Stritenberger
quelle
1
Ich bin versucht, dies als neue Antwort zu markieren, aber vielleicht können wir den Rest der Details herausholen.
el2iot2
Dies erfordert mehr Sichtbarkeit oder muss in die akzeptierte Antwort einbezogen werden. Es ist eine viel bessere Lösung.
Lauraducky
Warum ist das besser? Zuerst dachte ich, dass die akzeptierte Antwort auch zur Laufzeit unnötig Scheinmodelle erzeugen würde, aber ich habe das getestet und das tut es tatsächlich nicht. Ressourcen werden nicht erstellt, wenn sie nicht verwendet werden.
Paul
@Paul Es ist wirklich eine Frage der Präferenz, aber diese Antwort behält den gesamten Kontext der Entwurfszeitdaten in einer Deklaration bei, anstatt ihn an zwei Stellen zu haben. Erleichtert Änderungen
John Stritenberger
1
@JohnStritenberger Es ist nicht nur eine Präferenz, die akzeptierte Antwort lädt unnötigerweise Ressourcen für alle Zeiten in den Speicher, nicht nur für den Designer.
UuDdLrLrSs
4

Karl Shifflett beschreibt einen Ansatz, der für VS2008 und VS2010 gleich gut funktionieren sollte:

Anzeigen von Entwurfszeitdaten in Visual Studio 2008 Cider Designer in WPF- und Silverlight-Projekten

Laurent Bugnion verfolgt einen ähnlichen Ansatz, der sich auf Expression Blend konzentriert. Es könnte für VS2010 funktionieren, aber ich habe dies noch nicht bestätigt.

Simulieren von Daten im Entwurfsmodus in Microsoft Expression Blend

dthrasher
quelle
Vielen Dank, dass Sie mich darauf aufmerksam gemacht haben. Ich mag das DesignAndRunTimeDataContext-Konzept.
el2iot2
1
Karl Shifflett hat einen aktualisierten Artikel für Visual Studio 2010: Beispieldaten im WPF und Silverlight Designer
totorocat
1
Der Kern des Linkinhalts sollte wirklich in die Antwort eingearbeitet werden, zumal der erste Link jetzt tot ist.
Lauraducky
4

Möglicherweise sind die neuen Design-Time-Funktionen von Visual Studio 2010 und Expression Blend 4 eine Option für Sie.

Wie es funktioniert, zeigt die BookLibrary- Beispielanwendung des WPF Application Framework (WAF) . Bitte laden Sie die .NET4-Version herunter.

jbe
quelle
Danke für den Link. Gibt es eine bestimmte Codedatei oder ein bestimmtes Konstrukt, auf das ich achten sollte, um den Ansatz zu sehen? (eine kurze Übersicht wäre toll)
el2iot2
Schauen Sie sich das Projekt BookLibrary.Presentation an. In diesem Projekt finden Sie den Ordner "DesignData", der von den UserControls verwendet wird, im Ordner "Views".
13.
1
+1. Hab mir das mal angesehen. Für alle Interessierten wird das Beispieldatenansichtsmodell in XAML deklariert und über d: DataContext = "{d: DesignData Source = .. / DesignData / SampleLendToViewModel.xaml}"
RichardOD
4

Ich verwende diesen Ansatz zum Generieren von Entwurfszeitdaten mit .NET 4.5 und Visual Studio 2013.

Ich habe nur ein ViewModel. Das Ansichtsmodell verfügt über eine Eigenschaft, IsInDesignModedie angibt, ob der Entwurfsmodus aktiv ist oder nicht (siehe Klasse ViewModelBase). Anschließend können Sie Ihre Entwurfszeitdaten (z. B. das Füllen eines Elementsteuerelements) im Konstruktor für Ansichtsmodelle einrichten.

Außerdem würde ich keine realen Daten in den View Models-Konstruktor laden. Dies kann zur Laufzeit zu Problemen führen, aber das Einrichten von Daten für die Entwurfszeit sollte kein Problem sein.

public abstract class ViewModelBase
{
    public bool IsInDesignMode
    {
        get
        {
            return DesignerProperties.GetIsInDesignMode(new DependencyObject());
        }
    }
}

public class ExampleViewModel : ViewModelBase
{
    public ExampleViewModel()
    {
        if (IsInDesignMode == true)
        {
            LoadDesignTimeData();
        }
    }

    private void LoadDesignTimeData()
    {
        // Load design time data here
    }       
}
Martin
quelle
4

Mit Visual Studio 2017 habe ich versucht, alle Anleitungen und Fragen wie diese zu befolgen, und ich war immer noch mit einer konfrontiert, <ItemsControl>die den Code, den ich im Konstruktor von a hatte, von DesignFooViewModeldem erbt, einfach nicht ausführte FooViewModel. Ich habe den Teil "nicht ausgeführt" gemäß dieser "praktischen" MSDN-Anleitung (Spoiler: MessageBoxDebugging) bestätigt. Dies hängt zwar nicht direkt mit der ursprünglichen Frage zusammen, ich hoffe jedoch, dass andere dadurch viel Zeit sparen.

Es stellte sich heraus, dass ich nichts falsch gemacht habe. Das Problem war, dass meine Anwendung für x64 erstellt werden muss. Da das Visual Studio noch im Jahr 2018 ein 32-Bit-Prozess ist und anscheinend keinen 64-Bit-Host-Prozess für den Designer-Teil drehen kann, kann es meine x64-Klassen nicht verwenden. Das wirklich Schlimme ist, dass in keinem Protokoll, das mir einfällt, Fehler zu finden sind.

Wenn Sie also auf diese Frage stoßen, weil Sie falsche Daten in Ihrem Entwurfszeitansichtsmodell sehen (zum Beispiel: wird <TextBlock Text="{Binding Name}"/>angezeigt, Nameunabhängig davon, auf was Sie die Eigenschaft setzen), ist die Ursache wahrscheinlich Ihr x64-Build. Wenn Sie Ihre Build-Konfiguration aufgrund von Abhängigkeiten nicht in anycpu oder x86 ändern können, sollten Sie ein neues Projekt erstellen, das vollständig anycpu ist und keine Abhängigkeiten (oder Abhängigkeiten) aufweist. Am Ende teilen Sie also die meisten oder alle Teile außer dem Initialisierungsteil des Codes von Ihrem "WPF App" -Projekt in ein "C # -Klassenbibliothek" -Projekt auf.

Für die Codebasis, an der ich arbeite, denke ich, dass dies eine gesunde Trennung von Bedenken auf Kosten einer Code-Duplizierung erzwingen wird, was wahrscheinlich eine positive Netto-Sache ist.

joonas
quelle
3

Ähnlich wie bei der am besten bewerteten Antwort, aber meiner Meinung nach besser: Sie können eine statische Eigenschaft erstellen, um eine Instanz von Konstruktionsdaten zurückzugeben und wie folgt direkt von XAML zu referenzieren:

<d:UserControl.DataContext>
    <Binding Source="{x:Static designTimeNamespace:DesignTimeViewModels.MyViewModel}" />
</d:UserControl.DataContext>

Dies vermeidet die Notwendigkeit zu verwenden UserControl.Resources. Ihre statische Eigenschaft kann als Factory fungieren, sodass Sie nicht triviale Datentypen erstellen können. Wenn Sie beispielsweise keinen Standard-Ctor haben, können Sie hier eine Factory oder einen Container aufrufen, um entsprechende Abhängigkeiten einzufügen.

Jack Ukleja
quelle