Pendekatan apa yang tersedia untuk data waktu desain tiruan di WPF?

97

Saya bekerja tanpa campuran ekspresi dan hanya menggunakan editor XAML di vs2010. Terlepas dari kebijaksanaan ini, saya semakin melihat kebutuhan untuk pengikatan data waktu desain. Untuk kasus sederhana, FallbackValueproperti berfungsi dengan sangat baik (Textboxes dan TextBlocks, dll). Tetapi terutama ketika berhadapan dengan ItemsControldan sejenisnya, seseorang benar-benar membutuhkan data sampel untuk terlihat di perancang sehingga Anda dapat menyesuaikan dan mengubah kontrol dan templat data tanpa harus menjalankan yang dapat dieksekusi.

Saya tahu itu ObjectDataProvidermemungkinkan untuk mengikat suatu jenis, dan dengan demikian dapat memberikan data waktu desain untuk visualisasi, tetapi kemudian ada beberapa juggling untuk memungkinkan data real-time untuk mengikat tanpa membuang sumber daya dengan memuat memuat kedua waktu desain, data dummied dan binding runtime.

Sungguh apa yang saya inginkan adalah kemampuan untuk memiliki, katakanlah, "John", "Paul", "George", dan "Ringo" muncul di desainer XAML sebagai item bergaya di saya ItemsControl, tetapi memiliki data nyata yang muncul saat aplikasi lari.

Saya juga tahu bahwa Blend memungkinkan beberapa atribut mewah yang menentukan data pengikatan waktu desain yang secara efektif diabaikan oleh WPF dalam kondisi run-time.

Jadi pertanyaan saya adalah:

1. Bagaimana cara memanfaatkan binding waktu desain dari koleksi dan data non-sepele di desainer XAML studio visual dan kemudian menukar ke binding runtime dengan lancar?

2. Bagaimana orang lain memecahkan masalah data waktu desain vs. waktu proses ini? Dalam kasus saya, saya tidak dapat dengan mudah menggunakan data yang sama untuk keduanya (seperti yang dapat dilakukan dengan, katakanlah, kueri database).

3. Apakah alternatif mereka untuk campuran ekspresi yang dapat saya gunakan untuk desain XAML terintegrasi data? (Saya tahu ada beberapa alternatif, tetapi saya secara khusus menginginkan sesuatu yang dapat saya gunakan dan melihat data sampel terikat, dll?)

el2iot2
sumber

Jawaban:

120

Menggunakan VS2010 Anda dapat menggunakan atribut Design-Time (berfungsi untuk SL dan WPF). Saya biasanya memiliki sumber data tiruan jadi ini hanya masalah:

  • Menambahkan deklarasi namespace

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  • Menambahkan konteks data tiruan ke sumber daya jendela / kontrol

    <UserControl.Resources>
      <ViewModels:MockXViewModel x:Key="DesignViewModel"/>
    </UserControl.Resources>
  • Menetapkan konteks data waktu desain

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

Bekerja dengan cukup baik.

Goran
sumber
2
Jika Anda mengalami masalah dalam menggunakan, d:DataContextAnda mungkin menemukan beberapa bantuan dalam pertanyaan ini: stackoverflow.com/questions/8303803/…
Martin Liversage
27
Bukankah contoh ini akan menyebabkan instance MockXViewModel dimuat ke sumber daya Anda untuk build rilis? Apakah ini bukan masalah?
jpierson
12
FYI: Anda juga memerlukan yang berikut ini, atau kompiler VS2012 tidak akan mengkompilasi file xaml: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"danmc:Ignorable="d"
Orion Edwards
51
jpierson benar. Saya lebih suka menggunakan <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" .... Dengan cara ini, model tampilan tiruan hanya akan dibuat di desainer, tidak saat menjalankan aplikasi Anda. Ingat, pendekatan ini mengharuskan model tampilan tiruan Anda memiliki konstruktor tanpa parameter. Tetapi kasus yang sama terjadi pada contoh yang diberikan di atas dalam jawaban.
René
2
@ René pendekatan Anda jauh lebih baik. Silakan tambahkan sebagai jawaban dan saya akan memilihnya
dss539
15

Sebagai campuran dari jawaban yang diterima Goran dan komentar Rene yang sangat bagus.

  • Tambahkan deklarasi namespace. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

  • Referensi konteks data waktu desain Anda dari kode.
    <Grid d:DataContext="{d:DesignInstance Type=ViewModels:MockXViewModel, IsDesignTimeCreatable=True}" ...

John Stritenberger
sumber
1
Saya tergoda untuk menandai ini sebagai jawaban baru, tetapi mungkin kita dapat menarik detail lainnya.
el2iot2
Ini membutuhkan lebih banyak visibilitas, atau perlu ditarik ke jawaban yang diterima. Ini solusi yang jauh lebih baik.
Lauraducky
Mengapa ini lebih baik? Pada awalnya saya berpikir bahwa jawaban yang diterima tidak perlu menghasilkan model tiruan juga dalam runtime tetapi saya mengujinya dan ternyata tidak. Sumber daya tidak dibuat jika tidak digunakan.
Paul
@Paul Ini benar-benar masalah preferensi, tetapi jawaban ini menjaga seluruh konteks data waktu desain dalam satu deklarasi vs menyimpannya di dua tempat. Membuat perubahan lebih mudah
John Stritenberger
1
@JohnStritenberger Ini bukan hanya preferensi, jawaban yang diterima tidak perlu memuat sumber daya ke dalam memori sepanjang waktu, tidak hanya untuk desainer.
UuDdLrLrSs
4

Karl Shifflett menjelaskan pendekatan yang harus bekerja sama baiknya untuk VS2008 dan VS2010:

Melihat Data Waktu Desain di Visual Studio 2008 Cider Designer di Proyek WPF dan Silverlight

Laurent Bugnion memiliki pendekatan serupa yang berfokus pada Expression Blend. Ini mungkin berfungsi untuk VS2010, tetapi saya belum mengkonfirmasi ini.

Simulasi data dalam mode desain di Microsoft Expression Blend

dthrasher
sumber
Terima kasih sudah membawa ini padaku. Saya suka konsep DesignAndRunTimeDataContext.
el2iot2
1
Karl Shifflett memiliki artikel yang diperbarui untuk Visual Studio 2010: Contoh Data di WPF dan Silverlight Designer
totorocat
1
Inti dari konten tautan harus benar-benar diedit menjadi jawabannya, terutama karena tautan pertama sekarang sudah mati.
Lauraducky
4

Mungkin fitur desain-waktu baru dari Visual Studio 2010 dan Expression Blend 4 adalah pilihan untuk Anda.

Cara kerjanya ditunjukkan dalam contoh aplikasi BookLibrary dari WPF Application Framework (WAF) . Harap unduh versi .NET4.

jbe
sumber
Terima kasih untuk tautannya. Apakah ada file kode atau konstruksi tertentu yang harus saya lihat untuk melihat pendekatannya? (gambaran singkat akan sangat bagus)
el2iot2
Lihat proyek BookLibrary.Presentation. Dalam proyek ini Anda menemukan folder "DesignData" yang digunakan oleh UserControls di folder "Tampilan".
jbe
1
+1. Coba lihat ini. Bagi siapa pun yang tertarik, contoh model tampilan data dideklarasikan dalam XAML dan direferensikan melalui d: DataContext = "{d: DesignData Source = .. / DesignData / SampleLendToViewModel.xaml}"
RichardOD
4

Saya menggunakan pendekatan ini untuk menghasilkan data waktu desain dengan .NET 4.5 dan Visual Studio 2013.

Saya hanya memiliki satu ViewModel. Model tampilan memiliki properti IsInDesignModeyang memberitahu apakah mode desain aktif atau tidak (lihat kelas ViewModelBase). Kemudian Anda dapat menyiapkan data waktu desain Anda (seperti mengisi kontrol item) di konstruktor model tampilan.

Selain itu, saya tidak akan memuat data nyata dalam konstruktor model tampilan, ini dapat menyebabkan masalah saat runtime, tetapi menyiapkan data untuk waktu desain seharusnya tidak menjadi masalah.

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
sumber
4

Menggunakan Visual Studio 2017 saya telah mencoba untuk mengikuti semua panduan dan pertanyaan seperti ini dan saya masih menghadapi <ItemsControl>yang sama sekali tidak mengeksekusi kode yang saya miliki di dalam konstruktor DesignFooViewModelyang mewarisi FooViewModel. Saya mengkonfirmasi bagian "tidak mengeksekusi" mengikuti panduan MSDN yang "berguna" ini (spoiler: MessageBoxdebugging). Meskipun ini tidak terkait langsung dengan pertanyaan awal, saya berharap ini akan menghemat banyak waktu orang lain.

Ternyata saya tidak melakukan kesalahan. Masalahnya adalah aplikasi saya harus dibuat untuk x64. Karena Visual Studio masih pada 2018 proses 32-bit dan tampaknya tidak dapat memutar proses host 64-bit untuk bagian desainer tidak dapat menggunakan kelas x64 saya. Hal yang sangat buruk adalah tidak ada kesalahan yang ditemukan di log mana pun yang dapat saya pikirkan.

Jadi, jika Anda menemukan pertanyaan ini karena Anda melihat data palsu dengan model tampilan waktu desain Anda (misalnya: <TextBlock Text="{Binding Name}"/>muncul Nametidak peduli Anda menyetel properti ke) penyebabnya kemungkinan adalah build x64 Anda. Jika Anda tidak dapat mengubah konfigurasi build ke anycpu atau x86 karena ketergantungan, pertimbangkan untuk membuat proyek baru yang sepenuhnya anycpu dan tidak memiliki dependensi (atau dependensi apa pun). Jadi Anda akhirnya membagi sebagian besar atau semua kecuali bagian inisialisasi kode dari proyek "WPF App" Anda menjadi proyek "C # class library".

Untuk basis kode yang sedang saya kerjakan, saya pikir ini akan memaksa pemisahan kekhawatiran yang sehat dengan mengorbankan beberapa duplikasi kode yang mungkin merupakan hal positif bersih.

joonas
sumber
3

Mirip dengan jawaban teratas, tetapi lebih baik menurut saya: Anda dapat membuat properti statis untuk mengembalikan contoh data desain dan mereferensikannya langsung dari XAML seperti:

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

Ini menghindari kebutuhan untuk menggunakan UserControl.Resources. Properti statis Anda dapat berfungsi sebagai pabrik yang memungkinkan Anda membuat tipe data non-trivial - misalnya jika Anda tidak memiliki ctor default, Anda dapat memanggil pabrik atau container di sini untuk memasukkan dependensi yang sesuai.

Jack Ukleja
sumber