Posts Tagged With 'WPF'

  • May
  • 01
  • 2010

MEF’i basit bir WPF uygulaması ile daha iyi anlıyoruz…

Tags: , , | View: 1,165 | Comments:

Önceki bir kaç yazımda MEF(Managed Extensibility Framework) ile ilgili bir şeyler yazmış, kısaca ve basitçe anlatmaya çalışmıştım. Bu yazımda onları birleştirerek ve ilerki yazılarda da kullanabileceğimiz bir örnek olması adına MEF’in WPF ortamında basitçe uygulanmasına değinerek MEF’i biraz daha iyi anlamaya çalışacağız.

Biz yazılımcılar daha çok kod kavramını sevdiğimiz için :) çok karmaşık olmasa da diğer yazılara nazaran biraz daha kod örneği içeren bir yazı olacak bu şimdiden belirtim. Bu arada kodları elimden geldiğince çok basit yazıp, ilerleyen yazılarda başka konular ile onları değiştirerek biraz daha eli yüzü düzgün hale getireceğiz.

Ne yapacağız?

Gerçek hayatta kullanamayacağımız, anlamsız bir WPF “plugin” uygulaması yapıyor olacağız. Gerçek hayatta kullanamayacağız belki ama kullanılabilir uygulamalar yapmamız açısından vizyon katacak bir örnek olacak.

Başlıyoruz…

Öncelikle yandaki resimdeki gibi bir proje yapısı oluşturalım. “WPFMEF” ana WPF uygulamamız olacak. Bu uygulama, yüklenen “plugin”leri çalıştırmakla yükümlü olacak. “FirstWPFPlugin” ve “SecondWPFPlugin” projeleri ise “WPF User Control” olarak yaratacağımız, WPF’e kullanıcı kontrolü olarak yükleyeceğimiz,”plugin”ler olacak...”Common” projesi ise tüm uygulamalarda ortak olarak kullnabileceğimiz bileşenleri içerecek.

Ana uygulama…

“WPFMEF” projesi az önce belirttiğim gibi MEF ile oluşturduğumuz “plugin”leri çalıştaracak uygulama. Basitçe aşağıdaki gibi bir ekran görüntüsüne sahip.

Ya da aşağıdaki gibi bir XAML’e…

<Window x:Class="WPFMEF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="502" Width="775">
    <Window.Resources>
        <DataTemplate x:Key="ListBoxDataTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100"></ColumnDefinition>
                    <ColumnDefinition Width="90"></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0"  Text="{Binding Path=Name}"></TextBlock>
                <Button Grid.Column="1" Width="50" Content="Çalıştır" CommandParameter="{Binding Path=Name}" Click="Button_Click"></Button>
            </Grid>

        </DataTemplate>

    </Window.Resources>
    <Grid>
        <ListBox Height="374" ItemTemplate="{StaticResource ResourceKey=ListBoxDataTemplate}"   HorizontalAlignment="Left" Margin="12,54,0,0" Name="listBox1" VerticalAlignment="Top" Width="190" />
        <Label Content="Sistemde yüklü pluginler:" Height="28" HorizontalAlignment="Left" Margin="0,20,0,0" Name="label1" VerticalAlignment="Top" Width="190" />
        <Canvas Height="374" HorizontalAlignment="Left" Margin="211,54,0,0" Name="canvas1" VerticalAlignment="Top" Width="502" />
        <Label Content="Plugin içeriği" Height="28" HorizontalAlignment="Left" Margin="211,20,0,0" Name="label2" VerticalAlignment="Top" />
    </Grid>

</Window>

Fark etmiş olduğunuz gibi basit bir ekran…Plugin’lerin listeneceği bir “Listbox” ve seçilen “plugin”nin çalışması için bir “Canvas” kontrolü içeriyor temel olarak. Bu uygulama için “plugin”leri yönetecek bir uygulama demiştik en başta hatırlarsanız. Peki nasıl yönetecek?…

Bunun için bu projede PluginFactory diye bir sınıf yaratmamız lazım. Bu sınıf ile “plugin”lerimizi yöneteceğiz. Sonraki yazılarda da bu sınıfı geliştirip, güzelleştiriyor olacağım. Aşağıdaki kod parçası şimdilik işimize yarayacaktır. Yorum şeklinde kodları açıklamaya çalıştım.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition.Hosting;
using Common;
using System.Windows.Controls;

namespace WPFMEF
{
    public class PluginFactory
    {
        //Plugin'lerimiz yüklü olduğu dizin
        private string pluginPath;

        //Plugin'lerimizin yüklü olduğu dizinin
        //MEF tarafındaki karşılığı.Adından da
        //anlaşıldığı üzere katalog gibi düşünebiliriz.
        //Uygulamada Plugin'lerimizin tutulduğu
        //yer de diyebiliriz.
        private DirectoryCatalog catalog;

        //Import edilen Part'ların,yani plugin'lerin
        //yaşam sürecini sürdürdüğü kısım olarak tanımlamak
        //bu aşamada yeterli olacaktır.
        private CompositionContainer container;

        //PluginFactory sınıfımızı yaratıyoruz.
        //Bunun için dışarıdan, plugin'lerin sistem üzerinde
        //nerede olduklarını parametre olarak veriyoruz.
        //İçeride ilgili atamaları yapıp,gerekli nesneleri
        //yaratıyoruz.
        public PluginFactory(string pluginPath)
        {
            try
            {
                this.pluginPath = pluginPath;
                this.catalog = new DirectoryCatalog(pluginPath);
                this.container = new CompositionContainer(catalog);
            }
            catch (System.IO.DirectoryNotFoundException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        //Bu metod ile sisteme yüklenmiş tüm "MEF Part"larını,
        //ya da kendi tabirimiz ile "plugin"leri listeliyoruz.
        //Önceki yazılarımda bahsetmiş olduğum "metadata" bilgisine
        //sahip olan "plugin"leri listeliyoruz.
        public List<IPluginMetaData> GetAllPlugins()
        {
            List<IPluginMetaData> list = new List<IPluginMetaData>();

            //Burada kendi interface'imiz ile yarattığımız,MEF Part'larını
            //alıyoruz.Belirttiğimiz dizindeki diğer 'Part'lar bu sayede gelmeyecektir.
            //Ayrıca bu noktada yine kendi yarattığımız IPluginMetaData'sı ile
            //'Part'ları listemize ekliyoruz.
            //"PluginForWPF" parametresi 'Plugin'lerimizi işaretlediğimiz
            //bir kontrat bilgisi olarak bu metodda kullanılıyor. "Plugin" yaratırken
            //tekrardan dönüyor olacağız.
            var controllerExport = container.GetExports(typeof(IPlugin),
                                                        typeof(IPluginMetaData),
                                                        "PluginForWPF");
            //Yukarıdaki ifadeyi LINQ şeklinde kullanarak bir List<> tipindeki
            //değişkene atmak tabi ki mümkün.
            //Ancak biraz daha açık olması adına aşağıdaki gibi bir kod bloğunu
            //listemizi oluşturmak adına kullanabiliriz.
            foreach (var item in controllerExport)
            {
                if (item.Metadata is IPluginMetaData)
                    list.Add((IPluginMetaData)item.Metadata);

            }
            return list;

        }

        //Bu metod ile ismini verdiğimiz "Part"ı ya da kendi tabirimiz ile
        //"Plugin"ni çekip kullanıyoruz.Bir önceki metoddaki yaklaşımın
        //çok benzeri...
        public UserControl LoadPlugin(string name)
        {
            var controllerExport = container.GetExports(typeof(IPlugin),
                                                        typeof(IPluginMetaData),
                                                        "PluginForWPF");

            foreach (var item in controllerExport)
            {
                IPluginMetaData metaData = item.Metadata as IPluginMetaData;
                if (metaData.Name == name)
                {
                    return (UserControl)item.Value;
                }
            }

            return null;
        }

    }
}

Şimdi ana uygulamamızdan bu PluginFactory sınıfını kullanarak, ana ekranda “plugin”lerimizi yönetebileceğiz. Bunun için de ana uygulamızda aşağıdaki gibi bir kod kullanmamız gerekecek.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFMEF
{

    public partial class MainWindow : Window
    {
        private PluginFactory _pluginFactory;
        public MainWindow()
        {

            InitializeComponent();
            LoadPlugins();
        }

        //"Plugin"lerimizi yada MEF'deki adıyla Part'ları
        //Ekrandaki ListBox kontrolüne ekliyoruz. Bu sayede
        //sistem tarafından hangi "Part"lar yüklenmiş bunları
        //görebiliyoruz
        private void LoadPlugins()
        {
            _pluginFactory = new PluginFactory(@"C:\WpFPlugins");
            Binding binder = new Binding();
            binder.Source = _pluginFactory.GetAllPlugins();
            listBox1.SetBinding(ListBox.ItemsSourceProperty, binder);
        }

        //Yüklenen "Plugin"leri çalıştırmak için bu event'i kullanıyoruz.
        //Bu "event" ListBox kontrolünde listelenen "Plugin" isimlerine tıklandığı
        //zaman çalışan bir metod.
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            canvas1.Children.Clear();
            Button button = sender as Button;
            UserControl control = _pluginFactory.LoadPlugin(button.CommandParameter.ToString());
            canvas1.Children.Add(control);
        }
    }
}

Sıra geldi “Plugin”lere…

Öncelikle “Common” projesinde aşağıdaki gibi bir sınıf tanımlamamız lazım. Bu sınıf ile ilgili ayrıntıları önceki MEF yazılarımdan tekrar tazeleyebilirsiniz.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;

namespace Common
{
    //"Metadata"mızın içeriğni belirliyoruz.
    //Ne gibi bilgiler tutabileceğimizi istediğimiz gibi tanımlayabiliriz.
    public interface IPluginMetaData
    {
        string Name { get; }
        string Version { get; }
        string Author { get; }

    }

    public interface IPlugin
    { }

    //ExportAttribute tipinde, "Attribute" tanımlıyoruz ki
    //Yaratacağımız Part'da bu "Attribute"u kullanabilelim
    //Burda önemli olan constructor'da base'i çağırıp
    //ExportAttribute'da hangi arayüz ile tanımlama yapacağımızı belirtmek.
    [MetadataAttribute]
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class PluginMetadataAttribute : ExportAttribute
    {
        public PluginMetadataAttribute(string name, string version, string author)
            : base(typeof(IPluginMetaData))
        {
            Name = name;
            Version = version;
            Author = author;

        }

        //IPluginMetaData arayüzünde ki özellikleri burada da tanımlıyoruz
        //Hepsini tanımlama zorunda değiliz.Tanımlamadıklarımız varsayılan
        //değerleri ile gelecektir.
        public string Name { get; set; }
        public string Version { get; set; }
        public string Author { get; set; }

    }
}

Plugin’ler için gerekli temel şeyleri yarattıktan sonra, ilk plugin’imizi kodlayabiliriz. Yukarda da belirttiğim gibi, bu ilk plugin bir WPF kullanıcı kontrolü olacak.”FirstWPFPlugin” projesinde ilgili kodları yazıyor olacağız. Çok basit ve anlamsız bir arayüz oluşturalım isterseniz…

<UserControl x:Class="Plugins.FirstWPFPlugin"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Button Content="Tıklayalım Bakalım" Click="button1_Click" Height="23" HorizontalAlignment="Left" Margin="77,107,0,0" Name="button1" VerticalAlignment="Top" Width="135" />
        <Label  Content="Bu ilk WPF Plugin'inimiz." Height="28" HorizontalAlignment="Left" Margin="77,84,0,0" Name="label1" VerticalAlignment="Top" FontStretch="Expanded" Width="149" />
    </Grid>
</UserControl>

Şimdi de aynı anlamsızlıkta kod tarafını yazalım.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Common;
using System.ComponentModel.Composition;

namespace Plugins
{

    //Export, özelliğini bu yarattığımız kontrole vererek
    //MEF'e bu kontrolün bir PART olarak Import edileceğini
    //söylüyoruz. Bu noktada IPlugin şeklinde önceden yarattığımız
    //interface'i de parametre olarak vermemiz gerekiyor.
    //MEF'de Export ettiğimiz tüm bileşenlerin belli bir kontart ismi
    //yada belli bir arayüz tipinden geliyor olması gerekmekte.
    //"PluginForWPF" bizim kontrat ismimiz, IPlugin'de arayüzümüz.
    [Export("PluginForWPF", typeof(IPlugin))]
    //PluginMetadata özelliği ise Export ettiğimiz sınıflara
    //ekstra olarak verebileceğimiz metadata bilgisini içeren,
    //yine kendi yarattığımız bir özellik sınıfı.
    [PluginMetadata("FirstWPFPlugin", "1.0", "Arda")]
    //Bu kısma ilerleyen yazılarda değiniyor olacağım
    [PartCreationPolicy(CreationPolicy.NonShared)]
    //WPF kullanıcı kontrolü olduğundan UserControl sınıfından
    //türüyor olması gerekmekte.IPlugin ise bizim kendi arayüzümüz.
    public partial class FirstWPFPlugin : UserControl,IPlugin
    {
        public FirstWPFPlugin()
        {
            InitializeComponent();
        }

        //Sanırım fazla açıklamaya gerek yok (:
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Hello world");
        }
    }
}

Bu projeyi “Build” edip daha sonra oluşan *.dll’i, ana uygulamamızın “plugin”leri kontrol ettiği dizin altına koymamız gerekmekte. Bu örnekte bu dizin “C:\WpfPlugins” oluyor…(:

Ana uygulamamız bu dizine bakıp, bu dizindeki “plugin”leri yüklüyor olacak. Uygulamayı çalıştırdığımızda aşağıdaki gibi bir ekran görüntüsü elde ediyor olacağız.

Umarım MEF ile ilgili olarak en azından bir şeylerin aklınızda oluşmasında yardımcı olan bir yazı olmuştur. İlerleyen yazılarda bu örnekleri geliştirip çok daha faydalı örnekler yapıyor olacağız. Bundan dolayı her türlü sorunuzu yada fikrinizi beklerim…

Not: Bu yazıdaki örnek kodları ve projeyi buradan indirebilirsiniz.(Visual Studio 2010 projesi)

Not: Yukarıda bahsettiğim “SecondWPFPlugin”den bahsetmedim ama ekteki kodlarda oda mevcut.

  • Jan
  • 31
  • 2010

WPF’de “ApplicationCommands” nedir?

Tags: , , | View: 488 | Comments:

Uygulamalarımızda standart bazı işlemleri yapma ihtiyacı duyabiliriz. “Cut”,”Copy”,”Paste” gibi… WPF bu standart işlemleri kendi uygulamalarımızda kolayca kullanabilmemizi “ApplicationCommands” kavramı ile sağlıyor. Ve bir çok kod kalabalığından bizi kurtarıyor.

Aşağıda yazdığım basit örnek üzerinden gidersek sanırım daha anlaşılır olacaktır.

1 <Grid>

2 <!–  –>

3 <TextBox Height=“23″ HorizontalAlignment=“Right” Margin=“0,50,229,0″ Name=“txtText” VerticalAlignment=“Top” Width=“120″ />

4 <Menu Margin=“0,0,0,285″>

5 <MenuItem Command=“ApplicationCommands.Cut” Header=“Kes” />

6 <MenuItem Command=“ApplicationCommands.Copy” Header=“Kopyala” />

7 <MenuItem Command=“ApplicationCommands.Paste” Header=“Yapıştır” />

8 </Menu>

9

10 <!–

11 Bu düğmeye basıldığında ApplicationCommands.Cut komutu(Command) çalışacak.

12 Hangi kontrol üzerinden çalışacağını CommandTarget özelliği ile belirleyebiliyoruz.

13 txtSource isimli textbox içerisindeki değer,btnCut‘a bastığımız zaman “Cut” komutu

14 clipboard tarafında gerekli işlemi yapacaktır.

15 –>

16 <Button x:Name=“btnCut” Content=“Kes” Command=“ApplicationCommands.Cut” CommandTarget=“{Binding ElementName=txtSource}” Margin=“12,120,384,161″></Button>

17 <TextBox x:Name=“txtSource” Margin=“125,120,177,161″></TextBox>

18 </Grid>

Yukarıdaki kod bloğunda görmüş olduğunuz gibi bir tane “Menu” yaratıyoruz. Bu menünün 3 tane “MenuItem”ı var. Standart bir uygulamadıki “Kes”,”Kopyala”,”Yapıştır” işlemlerini yapıyor. Bu menü elemanlarına basıldığında ne yapılacağını “Command” özelliğini kullanarak belirtebiliyoruz. Bu örneğimizde “ApplicationCommands” kavramından bahsediyor olduğumdan dolayı, “ApplicationCommands.Cut”,”ApplicationCommands.Copy”,”ApplicationCommands.Paste” komutlarını kullandık. Bu komutlar sayesinde bu standart işlemler için ekstra bir şey yapmamıza gerek yok. Tabi ki uygulamamızın özelliklerine göre kendi “Command”(komutlarımızı) yazabiliriz.

Uygulamamızı çalıştırdığımız zaman aşağıdaki gibi bir ekran görüntüsü bizi karşılayacaktır.

Dikkat ederseniz tüm menü elemanları ve diğer “Kes” düğmemiz aktif değil. Bunun nedeni “ApplicationCommands” ilgili komutları bizim için yönetiyor olması. Uygulamamızda kesip yada kopyalanacak bir şey olmadığından dolayı ilgili komutların tüm tetikleyicileri aktif değil. Bu uygulama dışında her hangi başka bir uygulamadan bir kopyalama ya da kesme işlemi yapıp bu uygulamaya döndüğünüzde menüdeki “Yapıştır” elemanının aktif olduğunu göreceksiniz.

Ya da büyük kes düğmesinin yanındaki TextBox’a herhangi bir değer girip seçtiğinizde, “Kes” düğmesinin aktif olduğunu göreceksiniz.Bunun nedeni “Kes” düğmesinin “CommandTarget” özeliğinin TextBox’a ayarlanmış olması.

“Kes” düğmesine bastığımzda, tekrardan “Kes” düğmesi aktifliğini kaybedecektir. Eğer ekrandaki hiç bir TextBox’da “focus” yok ise menüdeki “Yapıştır” elemanının aktif olmaması dikkatinizi  çekmiştir. Bunun nedeni de “Yapıştır” işleminin yapılacağı her hangi bir kontrolün seçilmemiş olması. Menünün altında ki TextBox’ı seçtiğimizde ve “Yapıştır” dediğimizde kestiğimiz yazının yapıştığını göreceksiniz.Bu kadar basit…:)

ApplicationCommands gibi, WPF’de  ”NavigationCommands”, “MediaCommands”, “EditingCommands” ve  ”ComponentCommands” sınıflarıda bazı işlemler için bize kolaylıklar sunuyor.

Burada altınız çizmek istediğim bir nokta var. Dikkat ettiyseniz ApplicationCommands.Cut komutunu iki farklı WPF kontrolünde tanımladık ve her hangi başka bir işlem yapmadan bu komut aynı şekilde çalıştı. Bunun altında WPF ile beraber ortaya çıkan “Commands” kavramı yer almakta. İlerleyen yazılarda bundan da bahsediyor olacağım.

  • Jan
  • 30
  • 2010

WPF 4.0′da görev çubuğunda “icon” gösterimi…

Tags: , , , | View: 446 | Comments:

Önceki yazımda WPF 4.0′da Windows 7′nin görev çubuğundaki yeni özelliklerden ön izleme özelliğini kendi uygulamamızda nasıl kullanabileceğimizden ve ön izleme ekranından uygulamamıza nasıl komut gönderebileceğimizi basitçe bahsetmiştim. Bu sefer de yine görev çubuğunda çalışan uygulamızdaki durumları, çeşitli görseller ile nasıl kullanıcıyı bilgilendirebileceğimizden bahsedeceğim.

Windows 7′de, Windows Live Messenger’ın görev çubundaki görünümünü hatırlarsınız. WLM’deki durumunuza göre görev çubuğundaki “icon” da değişiyor.

Benzer bir işlemi kendi uygulamamızda yapmak WPF 4.0 ile çok kolay. Basit bir senaryo ile üzerinden geçersem, hem kullanım açısından fikir verir, hem de daha iyi anlaşılır sanırsam.

Basit bir mesajlaşma uygulaması senaryosu yaratalım. Uygulamamıza bir yerlerden mesaj geliyor olsun ve uygulamamız ile bu mesajları onaylıyor ve red edebiliyor olsun. Öncelikle arayüz için gerekli kodumuzu oluşturalım.

37 <Window x:Class=“ThumbNailDemo.MainWindow”

38 xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation”

39 xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml”

40 Title=“MainWindow” Height=“350″ Width=“525″>

41 <Window.Resources>

42 <!– Görev çubuğunda gözükecek “icon” –>

43 <DrawingImage x:Key=“imgMessage”>

44 <DrawingImage.Drawing>

45 <ImageDrawing ImageSource=“email.png”

46 Rect=“0,0,16,16″ />

47 </DrawingImage.Drawing>

48 </DrawingImage>

49 </Window.Resources>

50 <Window.TaskbarItemInfo>

51 <TaskbarItemInfo>

52 <TaskbarItemInfo.ThumbButtonInfos>

53 <!– Onay düğmesi –>

54 <ThumbButtonInfo ImageSource=“black.png”

55 Description=“Apply” Click=“ThumbButtonInfo_Click” CommandParameter=“Apply” />

56 <!–Ignore düğmesi–>

57 <ThumbButtonInfo ImageSource=“green.png”

58 Description=“Ignore” Click=“ThumbButtonInfo_Click” CommandParameter=“Ignore” />

59 </TaskbarItemInfo.ThumbButtonInfos>

60 </TaskbarItemInfo>

61 </Window.TaskbarItemInfo>

62 <Grid>

63 <TextBlock x:Name=“txtInfo” FontSize=“72″ TextAlignment=“Center”></TextBlock>

64 </Grid>

65 </Window>

Kod tarafında da aşağıdaki kodları yazmamız gerekmekte.

37 public partial class MainWindow : Window

38 {

39 private BackgroundWorker _backgroundWorker;

40 public MainWindow()

41 {

42 InitializeComponent();

43 _backgroundWorker = new BackgroundWorker();

44 _backgroundWorker.WorkerSupportsCancellation = true;

45 _backgroundWorker.WorkerReportsProgress = true;

46 _backgroundWorker.DoWork += new DoWorkEventHandler(_backgroundWorker_DoWork);

47 _backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(_backgroundWorker_ProgressChanged);

48 _backgroundWorker.RunWorkerAsync();

49 }

50

51 void _backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)

52 {

53 //Görev çubuğuna ilgili “icon” u ekliyoruz.

54 TaskbarItemInfo.Overlay = (ImageSource)Resources["imgMessage"];

55 }

56 void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)

57 {

58 //Sonradan mesaj gelmiş gibi simule etmek için Thread yardımını kullanıyoruz.

59 Thread.Sleep(6000);

60 _backgroundWorker.ReportProgress(100);

61 }

62

63

64 }

Yukarıdaki kod bloğunda uygulama çalıştıktan bir süre sonra uygulamanın görev çubuğundaki resmini değiştiriyoruz.Uygulamamızda bir değişiklik olduğu zaman, uygulama penceresi aktif olmasa bile bu değişiklikten haberdar olabiliyoruz bu sayede. TaskbarItemInfo.Overlay özelliğine verdiğimiz ImageSource’u ile nasıl bir görsel ile kullanıcıyı haberdar edebileceğimizi belirtmemiz yeterli.

Şimdi önceki yazıda anlatmaya çalıştığım öz izleme penceresindeki düğmeler ile mesajı onaylıyalım ya da red edelim. Onaylayınca “icon” kaybolacak, red edince hiç bir şey olmayacak.:) Bu kadar basit bir senaryomuz var.

Kod kısmına aşağıdaki gibi eklememizi yaptığımızda bu basit senaryomuz tamamlanmış olacak.

62 private void ThumbButtonInfo_Click(object sender, EventArgs e)

63 {

64 if (sender is ThumbButtonInfo)

65 {

66 ThumbButtonInfo button = (ThumbButtonInfo)sender;

67 if (button.CommandParameter.ToString() == “Apply”)

68 TaskbarItemInfo.Overlay = null;

69 }

70 }

Basitçe .NET 4.0 ile WPF’e gelen yeni özellikleri anlatmaya çalıştım. Umarım biraz da olsa birşey oluşturmuştur akıllarda. Bu çok basit örneği çeşitlendirip, çok daha güzel özellikler ile uygulamalarımızı geliştirmek bizim elimizde. Haydi bakalım…:D

  • Jan
  • 30
  • 2010

WPF 4.0′da “Taskbar ThumbNail” işlemleri…

Tags: , , , | View: 346 | Comments:

Windows Vista ve Windows 7′de ki görev çubuğundaki  ”Thumbnail”(önizleme) kavramı uygulamalarımıza yeni özellikler katmak adına güzel bir özellik olarak  karşımıza çıktı. Özellikle Windows 7′nin de yaygınlaşmaya başlaması “Thumbnail” ve “Jumplist” kavramlarını yazılımcılar olarak kendi uygulamalarımızda da kullanılabilir hale getirmemizi zorunlu hale getirecek gibi.

.NET Framework için “Windows API Code Pack” ile bu özellikleri kısmen olarak kendi geliştirdiğimiz uygulamalarda kullanabilir hale gelmiştik.

.NET Framework 4.0 ile WPF’de bu özellikleri biraz daha verimli olarak kullanabilir hale geliyoruz. System.Windows.Shell, namespace’i bize bu özellikleri WPF tarafında kullanmamız için gerekli nesneleri ve metotları sağlıyor. İlk olarak kısaca ve basitçe TaskbarItemInfo sınıfından bahsediyor olacağım.

TaskbarItemInfo, bize WPF ile geliştirdiğimiz uygulamamızın görev çubuğundaki ön izleme özelliğini kullanabilmemizi sağlıyor.Ek olarak bu ön izleme ekranına çeşitli düğmeler ile yeni özellikler katabiliyoruz.

28 <Window x:Class=“ThumbNailDemo.MainWindow”

29 xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation”

30 xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml”

31 Title=“MainWindow” Height=“350″ Width=“525″>

32

33 <Window.TaskbarItemInfo>

34 <TaskbarItemInfo>

35

36 <TaskbarItemInfo.ThumbButtonInfos>

37 <ThumbButtonInfo ImageSource=“black.png”

38 Description=“Button 1″ />

39 <ThumbButtonInfo ImageSource=“blue.png”

40 Description=“Button 2″ />

41 <ThumbButtonInfo ImageSource=“green.png”

42 Description=“Button 3″ />

43 </TaskbarItemInfo.ThumbButtonInfos>

44 </TaskbarItemInfo>

45 </Window.TaskbarItemInfo>

46 <Grid>

47 <TextBlock x:Name=“txtInfo” FontSize=“72″ TextAlignment=“Center”></TextBlock>

48 </Grid>

49 </Window>

Yukarıdaki kod örneğinde TaskbarItemInfo sınıfının “ThumbButtonInfos” özelliği ile ön izleme ekranımıza çeşitli düğmeler ekleyebiliyoruz. Uygulamamızı çalıştırdığımızda aşağıdaki gibi bir ön izleme ekranı bizi bekliyor olacak.

Fark edeceğiniz üzere ön izleme ekranında 3 tane düğme ekrana eklenmiş durumda.Bu sayede uygulamamızı tam ekran açmadan, görev çubuğunda iken çeşitli komutlar vererek, bazı operasyonları çok daha hızlı yapabilir hale gelebiliyoruz.  Yukarıdaki kod bloğuna bir kaç ekleme ile bu düğmelere tıklandığı zaman çeşitli metotlar çalıştırabiliyoruz.

28 <Window x:Class=“ThumbNailDemo.MainWindow”

29 xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation”

30 xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml”

31 Title=“MainWindow” Height=“350″ Width=“525″>

32

33 <Window.TaskbarItemInfo>

34 <TaskbarItemInfo>

35 <TaskbarItemInfo.ThumbButtonInfos>

36 <ThumbButtonInfo ImageSource=“black.png”

37 Description=“Button 1″ Click=“ThumbButtonInfo_Click” CommandParameter=“Button1″ />

38 <ThumbButtonInfo ImageSource=“blue.png”

39 Description=“Button 2″ Click=“ThumbButtonInfo_Click” CommandParameter=“Button2″ />

40 <ThumbButtonInfo ImageSource=“green.png”

41 Description=“Button 3″ Click=“ThumbButtonInfo_Click” CommandParameter=“Button3″ />

42 </TaskbarItemInfo.ThumbButtonInfos>

43 </TaskbarItemInfo>

44 </Window.TaskbarItemInfo>

45 <Grid>

46 <TextBlock x:Name=“txtInfo” FontSize=“72″ TextAlignment=“Center”></TextBlock>

47 </Grid>

48 </Window>

Kod tarafında da aşağıdaki gibi basit bir metot ile düğmeye tıklandığı zaman yapmak istediğimiz şeyleri yapabiliriz.

26 private void ThumbButtonInfo_Click(object sender, EventArgs e)

27 {

28 if (sender is ThumbButtonInfo)

29 {

30 ThumbButtonInfo button = (ThumbButtonInfo)sender;

31 txtInfo.Text = button.Description;

32 }

33 }

Oldukça basit bir şekilde .NET Framework 4.0 ve WPF ile Windows 7 ‘nin özelliklerini uygulamalarımızda kullanabilir hale geliyoruz. Artık belli bir senaryo dahilinde bu özellikleri kullanmak size kalmış. Ama biraz daha kurcalarsanız, bu konu ile ilgili çok daha fazla özelliğin .NET Framework 4.0 ile beraber geldiğini göreceksiniz.Şimdilik bu kadar…

  • Dec
  • 28
  • 2009

WPF’de “Routed Events”

Tags: , , | View: 513 | Comments:

Bir önceki yazımda WPF’de kontrol içerisindeki kontrollerde oluşan “event” sorunundan bahsetmiştim. Aslında sorun değil, WPF’deki “event” yaklaşımının biraz farklılaştığını belirtmeye çalışmıştım. Bu yazıda biraz daha derinlere girip, WPF’deki “Routed Events”‘den bahsetmeye çalışacağım.

WPF, kullanıcı deneyiminin uygulamalarda daha rahat bir şekilde uygulanmasını amaçlıyordu hatırlarsanız. WPF’in ortaya ilk çıktığından beri Microsoft’un altını çizdiği nokta bu yönde. Bu bağlamda, standart bilgisayar uygulamalarında ki standart arayüzler yerine kullanıcının çok daha kolay kullanabileceği bir arayüz sunmak ve bu arayüz ile sunulan bilgileri de daha anlamlı bir görsellikte sunarak kullanıcı deneyimini uygulamalara katmak WPF’in ilerlediği yollardan bir tanesi diyebiliriz. Bu yaklaşımdan dolayı, WPF ile beraber alıştığımız kullanıcı kontrollerinden farklı bir yapı karşımıza çıkıyor. Tıkladığımız düğmeler WPF ile beraber daha farklı amaçlar için kullanılabilir hale geliyor. Ya da bir çok elemandan, seçim yapabileceğimiz kullanıcı kontrolleri içerik olarak daha anlamlı bilgiler içermeye başlıyor.

Mesela bir düğme(button)nin içine resim koyarak, düğmenin görselliğine farklı anlamlar yükleyebiliyoruz.Bu çok basit bir örnek oldu gerçi ama demek istediğim, WPF’de kullanıcı kontrollerini, farklılaştırarak zenginleştirebiliyoruz. Kontrolleri iç içe kullanabiliyoruz. Bir “button”(düğme) içine “image”(resim) kontrollü koymak gibi. Katmanlı bir kullanıcı kontrolü yapısı var demek biraz daha netleştirebilir belki.

“Routed Events” kavramı da bu yapıdan dolayı ortaya çıkıyor. Yukarıda bahsettiğim kontroller üzerinden örneklendirmek daha anlaşılır olacak sanırım. Aşağıdaki uyduruk resimde(:)) bir “button” içinde “image” var.

Şimdi “button”a tıklandığı zaman “click” olayı oluşur bildiğiniz üzere. Ve tıklandığı zaman ne olmasını istiyorsanız bu olaya(event) denk gelen metodda ilgili kodu yazarsınız. “button” tıklandığı zaman ne oluyorsa, aynı işlem üzerinde “image” kontrolü olan “button”a tıklandığında da olmalı. Tıklanan alan “image” kontrolüne denk geliyorsa tıklama işleminin “button” tarafından da anlaşılıyor olması lazım. Bundan dolayı “image” üzerinde bazı işlemlerin, “image”ı içeren kontroller tarafından da algılanabiliyor olması lazım. WPF bu işlemi “routed events” kavramı ile gerçekleştiriyor.Özetle WPF’de bir “event” başka elemanlara yönlendirilebiliyor.

Bir önceki yazıda gerçekleşen olayın sebebi bu yani. WPF’de bir uygulama geliştirirken, “routed events” kavramını kendi geliştireceğiniz kontrollerde kullanmanız kaçınılmaz olacaktır. İlerleyen yazılarda bununla ilgili çok basit bir örnek göstermeye çalışıyor olacağım…Şimdilik bu kadar.

Not: “button” ve “image” anlaşılır bir örnek olması açısından kullandığım kavramlar. WPF’deki mevcut tüm yapılar için “routed events” kavramı geçerlidir.

  • Dec
  • 25
  • 2009

WPF’de SelectionChanged problemi

Tags: , , | View: 712 | Comments:

Geçen gün bir arkadaşımın WPF(Windows Presentation Foundation)’den çektiği dertleri Twitter’dan gördüm ve benzer bir sorunu yaşadığım için şaşkınlığını çok iyi anladım. WPF kavram olarak çok güzel şeyler vaad ediyor olsa da, açıkcası tam olarak oturmuş bir yapı olduğuna inanmıyorum. İlk çıktığı zamandan beri kendimce küçük uğraşlar ile WPF’i elimden geldiğince takip etmeye öğrenmeye çalıştım,çalışıyorum da. Diğer .NET Framework yapıları ile kıyaslandığında farklılıkları ve değişiklikler ciddi anlamda uğraştırıyor.Neyse çok dağıtmadan konuyu, özüne dönelim.

WPF’de “control” yapısı, ASP.NET ve Windows yapısına göre biraz daha farklı. Bu farklara değinmek şimdi uzayacağından sadece farklı olduğunun altını çizmek yeterli olacaktır şu aşamada.

Sorunumuz ne peki? TabControl içinde kullandığımız Listbox,Combobox gibi yapılarda “SelectionChanged” event’i(olayı) çalıştığı zaman tabcontrol’ün de “SelectionChanged” event’i çalışmakta.Bunun nedenlerini inceleyerek sorunu çözmek, WPF’i anlamak adına daha faydalı olacağından olayın en temeline inerek çözümü sunmaya çalışacağım.

WPF’de “Selector” diye bir sınıf var. Listbox,Combobox gibi seçme işleminin yapılabileceği kullanıcı kontrolleri bu sınıftan türemekte.  ”Select” operasyonunun yapılacağı kontrollerin “Selector”dan türemesi kavram olarak bakıldığında çok normal. WPF’de TabControl diye bildiğimiz sekmeli bir yapı sunan kontrolde WPF’de “Selector”dan türemekte.Yani ListBox,Combobox ve TabControl aynı kategoride diyebiliriz daha basitçe.Bu kontrollerin “SelectionChanged” event’i Selector sınıfından gelmekte ve dinlenmekte. TabControl’ün veya Combobox’ın ne yazık ki kendilerine özgü düzenlenmiş bir SelectionChanged event’i yok.Bundan dolayı “Selector.SelectionChanged” event’i tetiklendiği zaman Selector sınıfından türeyen sınıflarda bu event’i kontrol etmeye çalıştıklarında başarılı olacaklardır.Yani daha açık bir şekilde; TabControl’ün SelectionChanged event’inde çalışan bir metodu olduğunu varsayalım:

81 protected void TabControl1_SelectionChanged(object sender, SelectionChangedEventArgs e)

82 {

83 //tab seçildi

84 }

Aynı şekilde Tabcontrol’ün içindeki bir ComboBox’ın da aynı event’de çalışacak bir metodu olduğunu varsayalım:

86 protected void Combobox1_SelectionChanged(object sender, SelectionChangedEventArgs e)

87 {

88 //combox’da seçildi

89 }

Uygulama çalıştığı zaman ComboBox’dan bir seçim yaptığınızda, ComboBox’ı içeren kontrolün(TabControl oluyor bu durumda) de SelectionChanged olduğu zaman çalışacak metod da çalışacaktır…Çok ilginç değil mi? Bunun nedeni yukarıdaki kısa açıklama. Ama asıl nedeni WPF’de ki event mekanizması.WPF ile beraber Routed Events diye bir kavram hayatımıza giriyor.Bir sonraki yazımda bunun ne olduğunu anlatmaya çalışacağım, çünkü WPF ile uğraşanlar için oldukça önemli bir şey olduğuna inanıyorum.Neyse sorunumuza dönelim…Şimdi en son combobox’ı seçmiştik ve tab kontrolününde metodu çalışmıştı. Bunu istemiyoruz tabi ki…Peki ne yapacağız…

Event argümanlarının(e parametresi oluyor metoddaki) “Handled” diye bir özelliği var. Bu özelliği “true” olarak değiştirdiğiniz zaman oluşan olayı(event) yakalamış olduğumuzu belirtiyoruz.

86 protected void Combobox1_SelectionChanged(object sender, SelectionChangedEventArgs e)

87 {

88 //combox’da seçildi

89 e.Handled = true;

90 }

Bu sayede TabControl’ün event’i çalışmamış oluyor…WPF ile geliştirme yaparken, bu tarz sorunları aslında sorun olarak değilde, değişiklik olarak algılamak gerekiyor sanırım.Neyse şimdilik bu kadar…Her türlü soru,sorun,düşünce fikir paylaşımına açığım,bekliyorum…(:

  • Nov
  • 24
  • 2009

Fishbowl ve Facebook

Tags: , , | View: 272 | Comments:

Microsoft, Facebook SDK ve WPF ile çok güzel bir uygulama ile Facebook’u masaüstümüze getirmiş. Açık olan kaynak kodları ile geliştiricilere çok güzel bir örnek. Mutlaka indirin deneyin derim…Biraz daha gaz vermesi adına aşağıda bir kaç resim var.

Kaynak kod: http://fishbowl.codeplex.com/

Site: http://fishbowlclient.com/

fishbowl3

fishbowl2

fishbowl1

  • Nov
  • 05
  • 2007

WPF ve DataBinding

Tags: , , | View: 650 | Comments:

.NET Framework 3.0 ile beraber gelen alt bileşenlerden Windows Presentation Foundation uzaktan güzel gözüksede sanırım uygulama geliştirme aşamasında bir çok yazılım uzmanını zorlayan yapılardan biri. Bunun öncelikli nedenleri, henüz stabil bir uygulama geliştirme platformunun tam olarak sunulmaması ve dökümantasyonun yeterli olmaması gösterilebilir sanırım. WPF vizyonu yaygınlaştıkca dökümantasyon olayınında gelişeceğine inanıyorum.
 
Bu yazımda WPF’da databinding işlemlerinden bahsedeceğim. Önceki framework versiyonlarından farklı bir yaklaşıma sahip olan databinding işlemleri WPF’da gerçekten oldukça karışık. Bunun nedenlerinden biri kontrolleri bir birleri ile iç içe kullanabilme özelliğinin ve her bir kontrolü özelleştirme esnekliliğinin çok gelişmiş olması desem yanılmış olmam. WPF’da bir listbox’ın içine koyacağınız düğme üzerine tıklandığı zaman bir combobox’ın çıkıp,elemanlarını değişik türlerde gösterebilme esnekliği, geliştirme aşamasında baya zorluyor.

Bu yazı ile bu WPF’de kontrollere databinding nasıl yapılır giriş seviyesinde bunu anlatacağım. Yazının biraz daha net anlaşılması için XAML kavramı ve .NET Framework 3.0 konseptine yatkınlın sanırım gerekli olacaktır. Yapacağım örnek, bir combobox’ı database’den gelen bilgiler ile nasıl doldurabilir ve combobox’ın elemanlarını nasıl özelleştirebiliriz bunu gösteren basit bir uygulama olacak.

  • May
  • 15
  • 2007

WPF/E artık Silverlight

Tags: , | View: 220 | Comments:

Daha önceki yazılarımda bashettiğim WPF/E artık Silverlight olarak kullanıma sunuldu. Web 2.0 kavramının sadece Ajax teknolojisi olmadığının, gittikçe genişleyen bir konsept olduğunun sanırım en büyük örneklerinden biri bu Silverlight ve benzeri yenilikler.

Silverlight ile ilgili daha geniş bilgi için http://msdn2.microsoft.com/en-us/silverlight/default.aspx

  • Dec
  • 17
  • 2006

WPF/E

Tags: , | View: 362 | Comments:

WPF/E ( Windows Presentation Foundation/Everywhere) kod adında yeni bir plugin yayınladı. Teknik olarak bir plugin ancak bu plugin’nin arkasında büyük kavramlar yatıyor. WPF ile görsellikte yeni bir kapı açan Microsoft, WPF/E ile bazı eksiklikleri kapatmayı planlıyor. WPF ile yapılan browser application’lar platform bağlılığı yaratıyordu ve web’in bazı standartlarına uygun değildi. En basitinden WPF ile geliştirdiğiniz bir browser application’ını başka platformlarda çalıştırırken sorun yaşıyordunuz. Bu hem WPF’nin browser applicationları tarafındaki eksikliğiydi.Ancak WPF/E ile bu platform bağımlılığı kalkıyor ve web tarafında FLASH’e alternatif, hatta bence ileride FLASH’in yerini alabilecek bir kavram ortaya çıkıyor.

WPF/E, web tarafında interaktif uygulamalar sunmanızı sağlayan bir konsept.WPF bir alt kümesi demek çok yanlış olmaz. Alt yapısında .NET 3.0, ASP.NET ATLAS ve JavaScript’in güçlerini birleştirdiği bir mimari var. XAML olayının esnekliği ve kolaylığı web tarafında da oldukça etkileyici görsellikler sunmanızı sağlıyor.

Öncelikle bir kaç link paylaşmak istiyorum ki bazı şeyler daha anlaşılır olsun. Öncelikle http://www.microsoft.com/downloads/details.aspx?FamilyId=A3E29817-F841-46FC-A1D2-CEDC1ED5C948&displaylang=en adresinden WPF/E’nin December CTP’sini download etmeniz gerekiyor. Bu nasıl browser’ınızda flash animasyonlarını görebilmek için bir şey yüklemeniz gerekiyorsa o tarz oldukça küçük bir dosya. Ancak baştan hatırlamak istiyorum, bu CTP 18 Şubat 2007’ye de bitecek. Bu küçük download’u yaptıktan sonra http://channel9.msdn.com/playground/wpfe/PageTurn/default.html adresindeki WPF/E örneğini görebilirsiniz.

Eminim bu üstteki linkleri ziyaret ettikten sonra olaya bakış açınız değişecek. 2007’nin ortalarında tam olarak çıkması planlanan WPF/E şimdiden örnekleri ve çalışmalarıyla baya bir merak uyandıran bir kavram.Bakalım ileride daha neler olacak.