Contoh # 1: Saya memiliki tampilan yang ditampilkan dalam aplikasi MVVM saya (mari kita gunakan Silverlight untuk keperluan diskusi) dan saya mengklik tombol yang akan membawa saya ke halaman baru.
Contoh # 2: Tampilan yang sama memiliki tombol lain yang, ketika diklik, harus membuka tampilan detail di jendela anak (dialog).
Kita tahu bahwa akan ada objek Command yang diekspos oleh ViewModel kita yang terikat pada tombol dengan metode yang merespons klik pengguna. Tapi, bagaimana? Bagaimana kita menyelesaikan aksinya? Bahkan jika kita menggunakan layanan Navigasi, apa yang akan kita katakan?
Untuk lebih spesifik, dalam model Tampilan-pertama tradisional (seperti skema navigasi berbasis URL seperti di web atau kerangka kerja navigasi bawaan SL) objek Perintah harus tahu Tampilan apa yang akan ditampilkan selanjutnya. Itu tampaknya melewati batas ketika sampai pada pemisahan kekhawatiran yang dipromosikan oleh pola.
Di sisi lain, jika tombol tidak ditransfer ke objek Command dan berperilaku seperti hyperlink, aturan navigasi dapat didefinisikan dalam markup. Tetapi apakah kita ingin agar Views mengendalikan aliran aplikasi dan bukankah navigasi hanyalah tipe lain dari logika bisnis? (Saya bisa mengatakan ya dalam beberapa kasus dan tidak dalam kasus lain.)
Bagi saya, implementasi utopis dari pola MVVM (dan saya pernah mendengar orang lain mengaku) akan memiliki kabel ViewModel sedemikian rupa sehingga aplikasi dapat berjalan tanpa kepala (yaitu tidak ada Views). Ini memberikan area permukaan paling luas untuk pengujian berbasis kode dan membuat Tampilan menjadi kulit asli pada aplikasi. Dan ViewModel saya seharusnya tidak peduli jika itu ditampilkan di jendela utama, panel mengambang atau jendela anak, bukan?
Menurut apprach ini, tergantung pada beberapa mekanisme lain saat runtime untuk 'mengikat' tampilan apa yang harus ditampilkan untuk setiap ViewModel. Tetapi bagaimana jika kita ingin berbagi Tampilan dengan banyak ViewModels atau sebaliknya?
Jadi mengingat kebutuhan untuk mengelola hubungan View-ViewModel sehingga kita tahu apa yang harus ditampilkan ketika bersama dengan kebutuhan untuk menavigasi antara tampilan, termasuk menampilkan jendela anak / dialog, bagaimana kita benar-benar mencapai ini dalam pola MVVM?
sumber
DataTemplateSelector
, yang biasanya saya gunakan untuk aplikasi Silverlight. 2) Saya telah menggunakan ini dalam banyak-ke-banyak situasi sebelumnya. Misalnya, satu ViewModel dapat memiliki beberapa Tampilan, atau satu Tampilan dapat dikaitkan dengan beberapa ViewModels. Untuk contoh yang pertama, lihat rachel53461.wordpress.com/2011/05/28/… . Untuk nanti, Anda hanya perlu menentukan beberapa peta ViewModels ke tampilan yang sama di DataTemplateSelector Anda.CurrentPages
4) Sekali lagi, itu hanya contoh dasar. Pada kenyataannya, PageViewModels saya semua didasarkan pada beberapa kelas dasar, jadi ShellViewModel saya hanya berfungsi dengan kelas dasar atau antarmuka, sepertiIPageViewModel
. Sungguh bagian terbesar dari pemetaan yang berantakan adalah DataTemplateSelector yang harus memetakan 40 Views ke 40 ViewModels.Demi penutupan, saya pikir saya akan memposting arah yang akhirnya saya pilih untuk menyelesaikan masalah ini.
Keputusan pertama adalah memanfaatkan kerangka kerja Navigasi Halaman Silverlight yang disediakan di luar kotak. Keputusan ini didasarkan pada beberapa faktor termasuk pengetahuan bahwa jenis navigasi ini sedang dilakukan oleh Microsoft ke dalam aplikasi Metro Windows 8 dan konsisten dengan navigasi di aplikasi Phone 7.
Untuk membuatnya bekerja, saya selanjutnya melihat pekerjaan yang dilakukan ASP.NET MVC dengan navigasi berbasis konvensi. Kontrol Frame menggunakan URI untuk menemukan 'halaman' yang akan ditampilkan. Kesamaan menyediakan kesempatan untuk menggunakan pendekatan berbasis konvensi serupa di aplikasi Silverlight. Caranya adalah membuat semuanya bekerja bersama dengan cara MVVM.
Solusinya adalah NavigationService. Layanan ini memaparkan beberapa metode, seperti NavigateTo dan Kembali, yang dapat digunakan ViewModels untuk memulai perubahan halaman. Ketika halaman baru diminta, NavigationService mengirimkan CurrentPageChangedMessage menggunakan fitur MVVMLight Messenger.
Tampilan yang berisi kontrol Frame memiliki ViewModel sendiri yang ditetapkan sebagai DataContext yang mendengarkan pesan ini. Saat diterima, nama tampilan baru dimasukkan melalui fungsi pemetaan yang menerapkan aturan konvensi kami dan disetel ke properti CurrentPage. Properti Sumber dari kontrol Frame terikat ke properti CurrentPage. Akibatnya, pengaturan properti memperbarui Sumber dan memicu navigasi.
Kembali ke Layanan Navigasi. Metode NavigateTo menerima nama halaman target. Untuk memastikan bahwa ViewModels tidak memiliki masalah UI, nama yang digunakan adalah nama ViewModel untuk ditampilkan. Saya benar-benar membuat enumerasi yang memiliki bidang untuk setiap ViewModel yang dapat dinavigasi sebagai penolong dan untuk menghilangkan string sihir di seluruh aplikasi. Fungsi pemetaan yang saya sebutkan di atas akan menghapus akhiran "ViewModel" dari nama, menambahkan "Halaman" ke nama dan mengatur nama lengkap menjadi "Tampilan {Nama} Halaman.xaml".
Jadi, misalnya, untuk menavigasi ke tampilan detail pelanggan, saya dapat menelepon:
Nilai dari CustomerDetails adalah "CustomerDetailsViewModel" yang dipetakan ke "Views \ CustomerDetailsPage.xaml".
Keindahan dari pendekatan ini adalah bahwa UI sepenuhnya dipisahkan dari ViewModels namun kami memiliki dukungan navigasi penuh. Namun saya sekarang dapat memeriksa kembali aplikasi saya dan kapan pun saya mau tanpa perubahan kode.
Semoga penjelasannya membantu.
sumber
Mirip dengan apa yang dikatakan Rachel, aplikasi saya yang kebanyakan-MVVM memiliki
Presenter
untuk menangani sakelar antar windows atau halaman. Rachel menyebut ini suatuApplicationViewModel
, tetapi dalam pengalaman saya, umumnya harus melakukan lebih dari sekadar menjadi target yang mengikat (seperti menerima pesan, membuat Windows, dll.) Sehingga secara teknis lebih seperti tradisionalPresenter
atauController
.Dalam aplikasi saya, saya
Presenter
mulai dengan aCurrentViewModel
. ThePresenter
memotong semua komunikasi antaraView
danViewModel
. Salah satu hal yangViewModel
dapat dilakukan selama interaksi adalah mengembalikan yang baruViewModel
, yang berarti halaman baru atau baruWindow
harus ditampilkan. YangPresenter
mengurus menciptakan atau menimpaView
untuk yang baruViewModel
dan mengaturDataContext
.Hasil dari suatu tindakan dapat juga bahwa a
ViewModel
adalah "lengkap", dalam halPresenter
ini mendeteksi ini dan menutup jendela, atauViewModel
mengeluarkan ini dari tumpukan VM dan kembali untuk menampilkan halaman sebelumnya.sumber
Presenter
baru saja menempel kembaliViewModel
di pohon visual, dan WPF mengambil yang sesuaiView
, menghubungkanDataContext
, dan menempatkan itu di pohon visual sebagai gantinya. Anda bisa melakukan ini dengan menggunakanDataTemplate
s yang menyatakanViewModel
jenis apa yang mereka render, atau Anda bisa membuat pemilih templat data kustom. Itu masih dalam ranah fitur WPF.