Geçenlerde, aylardır üzerinde çalıştığım güzelim WPF kütüphanemdeki bir UserControl'ü, yeni bir ana uygulama projesinde kullanmaya karar verdim. Her şey hazırdı, referansı ekledim, XAML'de namespace'i tanımladım, kontrolü yerleştirdim. Derleme tamam, çalıştırayım dedim... BAM! Ekran bomboş. Kontrol görünmüyor. Hemen Output penceresine baktım, gözlerime inanamadım.
XML:
System.Windows.ResourceDictionary Warning: 9 : Resource not found; ResourceKey='ModernButtonStyle'...
Kafayı yiyecektim. Meğerse sorun, UserControl'ün XAML'inde tanımlı ResourceDictionary referanslarındaymış. Kütüphane projesinde mükemmel çalışan şu yol:
XML:
Source="/MyCoolLibrary;component/Styles/Buttons.xaml"
Ana uygulamaya taşıyınca, bu göreceli yol (pack URI) bir anda havada kaldı. Çünkü ana uygulamanın assembly'si farklı (MyAwesomeApp), ve o yolun içinde MyCoolLibrary diye bir şey aramaya kalktı. Tabii ki bulamadı, stil uygulanmadı, kontrol de görünmez oldu.
İlk içgüdüm, yolu mutlak yapmaktı. "Şu component/ ifadesini kaldırayım, düzelir" diye düşündüm. Olmadı. Sonra mergedDictionaries'i ana uygulamanın App.xaml'ına taşımayı denedim. İşe yaradı ama bu sefer de kütüphanemi bağımsız test edemez oldum. Kütüphane projesini tek başına çalıştırdığımda kaynaklar yine kırılıyordu. İki tarafı da memnun edecek bir yol lazımdı.
StackOverflow'da bile tam oturan bir cevap bulamadım. Herkesin farklı bir hikayesi vardı. Nihayetinde, biraz deneme yanılma ve biraz da reflector ile inceleme sonucu şu iki pratik çözümden birine karar verdim:
1. Assembly Çapında Resource Tanımı: En temizi, resource dictionary'leri ComponentResourceKey kullanarak tanımlamak. Böylece kaynak, tanımlandığı assembly'den (MyCoolLibrary) gelir, nerede kullanılırsa kullanılsın.
2. Build Action'ı Değiştirmek: Dictionary dosyasının Build Action'ını Page yapıp, Copy Output'u Do not copy olarak ayarlamak. Bu, derleme sırasında kaynağı binary'ye gömülmesini sağlayabiliyor ve yol karmaşasını ortadan kaldırıyor.
Şaka gibi ama, WPF'de böyle basit bir şey için saatler harcadım. Aslında olay, pack URI sisteminin derinliklerinde ve assembly'ler arası kaynak çözümlemesinde yatıyor. Kütüphane geliştirirken, resource'ları dışarı taşınabilir şekilde tasarlamak çok önemliymiş, acı bir şekilde öğrendim.
Siz de böyle "göreceli yol" saçmalıkları yüzünden WPF'de kafayı yediğiniz oldu mu? UserControl kütüphanelerinizdeki stilleri taşınabilir yapmak için hangi yöntemi kullanıyorsunuz? Daha temiz bir çözümü olan var mı?