Silverlight UserControl'üm Design modunda Blend içinde mi? Yoksa gerçek hayatta mı?
Bugün sizlerle ufak fakat bence bir o kadar da değerli bir ip ucu paylaşacağım. Üzerinde çalıştığımız projelerden birinde hiç hoş olmayan bir sorun ile karşılaştık. Aslında sorunun nedeni Visual Studio ve Expression Blend içerisinde Silverlight projeleri düzenlenirken söz konusu projeler içerisindeki UserControl'lerin PageLoad ve Init kodlarının tasarım aşamasında da çalıştırılıyor olması. Ne demek istiyorum?
Örneğin Detay adında bir UserControl hazırladınız ve bunu da Ana adında bir UserControl'ün içerisine yerleştirdiniz. Bu yerleştirme işlemini de XAML içerisinde namespace tanımlayarak yaptınız ki tasarımcı Blend içerisinde söz konusu UserControl'ü rahatlıkla düzenleyebilsin. Özetle UserControl'lerinizin XAML kodları aşağıdaki gibi olsun;
[Ana.xaml]
<UserControl x:Class="SilverlightApplication27.Ana"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300" xmlns:SilverlightApplication27="clr-namespace:SilverlightApplication27" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock x:Name="Metin" Text="DENEME"/>
<SilverlightApplication27:Detay Margin="83,61,217,139" d:LayoutOverrides="VerticalAlignment"/>
</Grid>
</UserControl>
Gördüğünüz üzere diğer UserControl'ü almak üzere XAML NameSpace tanımı yapılmış ve ekrana da Detay adındaki UserControl yerleştirilmiş.
[Detay.xaml]
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="SilverlightApplication27.Detay"
d:DesignWidth="100" d:DesignHeight="100">
<Grid x:Name="LayoutRoot">
<Grid/>
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" Text="TextBlock" TextWrapping="Wrap" x:Name="Metin"/>
</Grid>
</UserControl>
Yukarıdaki şekli ile tanımladığımız Detay adındaki UserControl içerisinde de sadece bir TextBlock bulunuyor. Detay'ın kodunda bir şekilde Page.Load durumunda ekrandaki kontrollere veri bağlarsanız tüm bu işlemlerin Expression Blend içerisinde Ana.XAML açıldığında çalıştırıldığını göreceksiniz. Sonuç itibari ile Ana.XAML içerisine Detay kontrolünü koyduğumuz için Blend Ana adındaki UserControl içerisinde göstermek üzere Detay'ı çalıştırıp doğrudan sahneye yerleştiriyor. "Ne kadar güzel?" dediğinizi duyar gibiyim :) Aslında durum gerçekten hoş. Bu sistem sayesinde ana bir kontrole yerleştirilmiş UserControl'ler kendi Page.Load'ları da çalıştırılarak gerçek çalışır hallerindeki görüntüleri ile tasarımcıya gösteriliyorlar. Fakat ya Page.Load'da çalışan kod uygulamanın bir web sunucu üzerinden host edilmiş olmasını gerektiriyorsa? İşte tam da o noktada Blend çatlıyor :) doğal olarak....
Peki ne yapmak gerek?
Çözüm basit. Bizim UserControl'lerin kendilerinin Blend'de mi yoksa gerçekten çalışma zamanında da çalıştırıldıklarını algılamaları ve ona uygun işlem yapmaları gerekiyor. Örneğin bizim detay adındaki UserControl Blend tarafından açıldığında kendi içindeki TextBlock'e "DENEME" yazarken, gerçekten açıldığında ise sunucudan veri çekmeli.
[VB]
If Not ComponentModel.DesignerProperties.GetIsInDesignMode(Me) Then
MyServis.GetNewsFromBlogAsync()
Else
textBlock.Text = "Blend içerisinde blog ile bağlantı kurulamaz."
End If
Yukarıda gördüğünüz kod ile herhangi bir UIElement'in Blend içerisinde Design modunda açılıp açılmadığını öğrenebiliyorsunuz. Örneğin bizim örneğimizde normal şartlarda web servisinden veri çeken kod eğer Blend içerisinde açılmış ise veri çekmek yerine uygun yere uygun mesajı yazıyor. Farklı örneklerde tasarımcıya yardımcı olmak amacı ile DataBind ettiğiniz kontrolleri belki de tasarımcı için kod içerisinde veri yaratıp databind edebilirsiniz. Oysa uygulama çalıştığında gerçek veri kaynağına yönelebilir.
GetIsInDesignMode metoduna parametre olarak herhangi bir UIElement verdiğinizde size Design modunda olunup olunmadığına dair Boolean bir değer döndürüyor.
Hepinize kolay gelsin ;)