Apakah mungkin untuk menetapkan kode di belakang kamus sumber daya di WPF untuk penanganan acara?

147

Apakah mungkin untuk menetapkan kode di belakang kamus sumber daya di WPF. Misalnya dalam kontrol pengguna untuk tombol Anda mendeklarasikannya di XAML. Kode penanganan peristiwa untuk klik tombol dilakukan dalam file kode di belakang kontrol. Jika saya membuat templat data dengan tombol bagaimana saya bisa menulis kode pengendali event untuk itu klik tombol dalam kamus sumber daya.

Crippeoblade
sumber
1
Cara yang benar untuk melakukan ini adalah dengan menggunakan perintah, itu juga memberi Anda kemampuan untuk mengaktifkan dan menonaktifkan tombol, sementara Anda bisa melakukannya dengan cara beberapa jawaban menyarankan baunya hack.
Aran Mulholland

Jawaban:

209

Saya pikir yang Anda tanyakan adalah Anda menginginkan file di belakang kode untuk ResourceDictionary. Anda benar-benar dapat melakukan ini! Bahkan, Anda melakukannya dengan cara yang sama seperti untuk Window:

Katakanlah Anda memiliki ResourceDictionary yang disebut MyResourceDictionary. Dalam file MyResourceDictionary.xaml Anda, letakkan atribut x: Class di elemen root, seperti:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    x:Class="MyCompany.MyProject.MyResourceDictionary"
                    x:ClassModifier="public">

Kemudian, buat kode di belakang file bernama MyResourceDictionary.xaml.cs dengan deklarasi berikut:

namespace MyCompany.MyProject
{
    partial class MyResourceDictionary : ResourceDictionary
    { 
       public MyResourceDictionary()
       {
          InitializeComponent();
       }     
       ... // event handlers ahead..
    }
}

Dan kamu sudah selesai. Anda dapat meletakkan apa pun yang Anda inginkan dalam kode di belakang: metode, properti, dan penangan event.

== Pembaruan untuk aplikasi Windows 10 ==

Dan untuk berjaga-jaga jika Anda bermain dengan UWP ada satu hal lagi yang harus diperhatikan:

<Application x:Class="SampleProject.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:rd="using:MyCompany.MyProject">
<!-- no need in x:ClassModifier="public" in the header above -->

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- This will NOT work -->
                <!-- <ResourceDictionary Source="/MyResourceDictionary.xaml" />-->

                <!-- Create instance of your custom dictionary instead of the above source reference -->
                <rd:MyResourceDictionary />

            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

</Application>
ageektrapped
sumber
7
Sebagai tambahan untuk jawaban ageektrapped: Pastikan bahwa Anda memasukkan nama yang sepenuhnya memenuhi syarat kelas codebehind Anda dalam atribut x: Class. x:Class="MyCompany.MyProject.MySubFolder1.MyResourceDictionary"Jika tidak, jika Anda hanya meletakkan x: Class = "MyResourceDictionary", parser xaml tidak akan menemukan kelas Anda.
viggity
29
Pastikan Anda memberikan konstruktor default di kode kelas parsial, dan pastikan itu memanggil InitializeComponent (). (Dalam kasus saya, saya menggunakan MEF untuk Mengekspor kamus sumber daya.)
Scott Whitlock
4
Cuplikan kode yang diperbarui untuk komentar yang ditingkatkan. Saya merasa perlu melengkapi jawabannya; kesalahan umum. Saya melakukannya sekarang :) Kembalikan jika Anda tidak menyukainya. Terima kasih atas jawabannya.
Gishu
2
Perhatikan bahwa (setidaknya dalam wp8.1) ini tidak lagi valid dan Anda harus membuat kontrol pengguna kustom yang dirujuk oleh sumber daya referensi kamus Anda
Jared
9
Anda juga harus mengatur Build Action pada file XAML ResourceDictionary ke "Page", jika tidak panggilan InitializeComponent () tidak akan dikompilasi. (File XAML ResourceDictionary biasanya diatur ke "Sumberdaya" secara default.)
user1454265
9

Saya tidak setuju dengan "ageektrapped" ... menggunakan metode kelas parsial bukan praktik yang baik. Apa tujuan memisahkan Kamus dari halaman itu?

Dari kode-belakang, Anda dapat mengakses kapak: Elemen nama dengan menggunakan:

Button myButton = this.GetTemplateChild("ButtonName") as Button;
if(myButton != null){
   ...
}

Anda dapat melakukan ini dalam metode OnApplyTemplate jika Anda ingin terhubung ke kontrol ketika kontrol kustom Anda dimuat. OnApplyTemplate perlu diganti untuk melakukan ini. Ini adalah praktik umum dan memungkinkan gaya Anda tetap terputus dari kontrol. (Gaya tidak harus bergantung pada kontrol, tetapi kontrol harus bergantung pada memiliki gaya).

Phobis
sumber
7
Phobis Saya pikir tujuan memisahkan Kamus dari halaman adalah tentang usabilitas dan keterbacaan halaman Utama xaml. Solusi di atas juga bekerja untuk saya.
cleftheris
5

Gishu - sementara ini mungkin tampak sebagai "latihan yang umumnya tidak dianjurkan" Ini adalah salah satu alasan Anda mungkin ingin melakukannya:

Perilaku standar untuk kotak teks ketika mereka mendapatkan fokus adalah agar tanda sisipan ditempatkan pada posisi yang sama ketika kontrol kehilangan fokus. Jika Anda lebih suka di seluruh aplikasi Anda bahwa ketika pengguna tab ke kotak teks apa pun bahwa seluruh isi kotak teks itu disorot maka menambahkan penangan sederhana dalam kamus sumber daya akan melakukan trik.

Alasan lain di mana Anda ingin perilaku interaksi pengguna default berbeda dari perilaku out of the box sepertinya kandidat yang baik untuk kode di belakang dalam kamus sumber daya.

Sepenuhnya setuju bahwa apa pun yang merupakan fungsionalitas aplikasi spesifik tidak boleh ada dalam kode di belakang kamus sumber daya.

Pete Maher
sumber
0

XAML adalah untuk membuat grafik objek yang tidak mengandung kode.
Templat Data digunakan untuk menunjukkan bagaimana objek pengguna kustom akan ditampilkan di layar ... (misalnya jika itu adalah item listbox) perilaku bukan bagian dari bidang keahlian templat data. Gambar ulang solusinya ...

Gishu
sumber
kesimpulan: Apakah Anda merekomendasikan untuk menggunakan sumber daya dic dengan kode di belakang atau tidak ?? Saya tidak pernah menggunakannya, saya ragu.
Shimmy Weitzhandler
1
Saya tidak akan - bagi saya rasanya tidak benar. Kamus harus mengembalikan nilai untuk kunci tertentu. Dalam kasus OP, bundling kode dengan templat data .. Saya lebih suka mencoba pendekatan yang berbeda .. gunakan model Command misalnya. Saya perlu rincian lebih lanjut tentang masalah OP untuk merekomendasikan solusi yang berbeda.
Gishu
1
Sepenuhnya tidak setuju. Dengan MVVM, ada satu skenario di mana memiliki kode di belakang sangat berguna: mengembangkan properti terlampir. Dapatkan bekerja dengan kode di belakang, lalu porting ke properti terlampir. Ini jauh lebih cepat daripada hanya mengembangkan properti terlampir dari awal, kecuali Anda memiliki ukuran otak Manhattan.
Contango