9 Mart 2012 Cuma

WPF Drag & Drop İşlemleri


Masaüstünden sürüklenen image dosyalarının uygulamamız içinde gösterimini sağlayacağız. Ufak bir Wpf uygulaması yaparak nasıl yapılabileceğini görelim. Hemen bir Wpf Application oluşturarak başlayalım.

 Öncelikle image ların gösterimi için uygulamamıza bir UserControl ekliyoruz.



UserControlümüze bir Image elementi ekliyoruz. Ben biraz daha derli toplu görünmesi için Image elementini Border içinde kullandım. UserControlümüzün Xaml kodlaması aşağıdaki gibidir.

<UserControl x:Class="DesktopFileDrop.ImageDropUI"
             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="250" d:DesignWidth="250" MaxHeight="250" MaxWidth="250">
    <Grid>
        <Border x:Name="brdContainer" Margin="20">
            <Image x:Name="imgViewer"></Image>
            <Border.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF7F9CA2" Offset="1" />
                    <GradientStop Color="#FFE9F0F5" Offset="0" />
                </LinearGradientBrush>
            </Border.Background>
        </Border>
    </Grid>
</UserControl>


İşimizi biraz daha kolaylaştırmak için UserControlümüzün Constructor ında Image elementimizin Source propertysini hemen set edebiliriz. Bunun için UserControlümüzün .cs tarafına geçiriyoruz ve Constructor ını Image elementimizin Source propertysini set etmek için kullanacağımız bir BitmapImage objesi parametre alacak şekilde değiştiriyor ve Image elementimizin Source propertysini bu parametremizle set ediyoruz.


using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace DesktopFileDrop
{
    /// <summary>
    /// Interaction logic for ImageDropUI.xaml
    /// </summary>
    public partial class ImageDropUI : UserControl
    {
        public ImageDropUI(BitmapImage bmpImage)
        {
            InitializeComponent();
            imgViewer.Source = bmpImage;
        }
    }
}

Artık image larımızı göstereceğimiz UserControlümüz kullanıma hazırdır. Şimdi MainWindow umuza geçelim ve hazırladığımız UserControlümüzü eklemek için bir container hazırlayalım. Bunun için ben WrapPanel kullanacağım, siz duruma göre farklı bir panel kullanabilirsiniz. Ayrıca panelimde scrool da çıkmasını istiyorum bunun içinde bir ScrollViewer elementi kullanacağım.
MainWindow umuzun Xaml kodlaması aşağıdaki gibidir.


 <Window x:Class="DesktopFileDrop.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="File Drop" Height="350" Width="550">
    <Grid AllowDrop="True" Drop="DropFile">
        <Label></Label>
        <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
            <WrapPanel x:Name="wrpContainer" FlowDirection="LeftToRight" Orientation="Horizontal" MaxWidth="550"></WrapPanel>
        </ScrollViewer>
    </Grid>
</Window>

Görüldüğü gibi en dıştaki Grid imizin AllowDrop propertysini True olarak set ettik. Formun sadece bir bölümünün üzerine gelindiğinde değilde her yerinde drop işlemine izin vermesini istiyoruz. Grid imiz tüm formu kapladığı için drop işlemini Grid in Drop Eventinde yapacağız. Şimdi MainWindow umuzun .cs tarafına geçelim ve Drop Eventimiz tetiklendiğinde imagelarımızın gösterimini yapacak kodlarımızı yazalım.
Öncelikle drop edilen dosyaların uzantılarını kontrol etmeliyiz. Biz image dosyası bekliyoruz ama kullanıcının farklı dosyalar drop etmeyeceğinden tabiki emin olamayız. Bu yüzden kabul edeceğimiz dosyaların uzantılarını bir yerde tutmamız gerekir.
Bu iş için hızlı bir çözüm olarak Uygulamanın Settings dosyasını kullanabiliriz. Settings dosyasının .cs inde AllowedImagePath isimli string bir property tanımlıyorum ve value suna izin verdiğim dosyların uzantılarını virgülle ayırarak ekliyorum. Bu işlemi Settings arayüzünden de yapabilirsiniz.

        [global::System.Configuration.UserScopedSettingAttribute()]
        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
        [global::System.Configuration.DefaultSettingValueAttribute(".jpg,.png,.bmp,.ico")]
        public string AllowedImagePath
        {
            get
            {
                return ((string)(this["AllowedImagePath"]));
            }
            set
            {
                this["AllowedImagePath"] = value;
            }
        }

MainWindow un contstructor ında bunları bir string dizisine alarak dosya uzantılarını buradan kontrol edebiliriz.

  private string[] _currentFileExtensions = null;

        public MainWindow()
        {
            InitializeComponent();
            _currentFileExtensions = DesktopFileDrop.Properties.Settings.Default.AllowedImagePath.Split(',');
        }

Şimdi kullanıcının drop ettiği dosyaların uzantılarını kontrol edecek methodumuzu yazalım. Methodumuz bizden bir FileInfo parametresi alsın ve bize boolean bir sonuç döndürsün.

 private bool CheckFileExtension(FileInfo file)
 {
            return _currentFileExtensions.Where(f => f == file.Extension).FirstOrDefault() == null ? false : true;
 }

Artık kullanıcının uygulamamıza sürüklediği dosya pathlerini alarak birer FileInfo nesnesi oluşturmalı ve biraz önce yazdığımız CheckFileExtension methodumuz ile dosya uzantılarının izin verdiğimiz uzantılar içinde olup olmadığını kontrol etmeliyiz. Sonrasında geçerli dosyaları, Image gösterimi için hazırlamış olduğumuz UserControlümüzü create ederken bizden beklediği BitmapImage nesnesini oluşturmak için kullanacağız ve create ettiğimiz her UserControlü MainWindow umuzdaki WrapPanelimize ekleyeceğiz.
Öncelikle kullanıcının drop ettiği dosyaların pathlerini almalıyız. Bu işlemi Grid imizin Drop eventinde DragEventArgs eventinden faydalanarak yapacağız.

private void DropFile(object sender, DragEventArgs e)
{
            string[] filePaths = e.Data.GetData(DataFormats.FileDrop) as string[];
            if (filePaths == null || filePaths.Count() == 0) { return; }

            CreateDropUserControls(CreateImage(GetFiles(filePaths)));
}

Kullanıcının uygulamamıza sürüklediği dosya pathlerini böylece almış olduk.
Şimdi aldığımız bu dosya pathlerini bizden parametre olarak alıp her biri için bir FileInfo nesnesi oluşturarak bize FileInfo Listesi döndürecek bir methoda ihtiyacımız var. Dosya uzantılarını kontrol etmek için yazdığımızCheckFileExtension methodumuzu da burada kullanacağız. Hemen FileInfo Listemizi oluşturacak methodumuzu yazmaya başlayalım.

private List<FileInfo> GetFiles(string[] filePaths)
{
            List<FileInfo> fileList = new List<FileInfo>();
            foreach (string path in filePaths)
            {
                try
                {
                    FileInfo file = new FileInfo(path);
                    if (file == null || !CheckFileExtension(file)) { continue; }
                    fileList.Add(file);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format("{0} dosyası yüklenemedi.\r\nException Message: {1}", path, ex.Message), "Hata!", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            return fileList;
 }

Sıra Image larımızı oluşturmaya geldi. Bunun içinde bizden parametre olarak FileInfo Listesi alıp geriye Image Listesi dönen bir methoda ihtiyacımız olacak.

private List<BitmapImage> CreateImage(List<FileInfo> fileList)
 {
            List<BitmapImage> imageList = new List<BitmapImage>();
            foreach (FileInfo file in fileList)
            {
                try
                {
                    BitmapImage bmp = new BitmapImage();
                    bmp.BeginInit();
                    bmp.UriSource = new Uri(file.FullName);
                    bmp.EndInit();
                    imageList.Add(bmp);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(string.Format("{0} imagı oluşturulamadı.\r\nException Message: {1}", file.Name, ex.Message), "Hata!", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            return imageList;
 }

Image larımızıda oluşturduğumuza göre artık bu Image larımızı göstereceğimiz UserControllemizi create edip, WrapPanelimize ekleyebiliriz.


private void CreateDropUserControls(List<BitmapImage> imageList)
 {
            foreach (BitmapImage image in imageList)
            {
                wrpContainer.Children.Add(new ImageDropUI(image));
            }
 }

CreateDropUserControls methodumuzu Grid imizin Drop eventinde çalıştırarak finali yapıyoruz. Drop eventimizin son hali aşağıdaki gibidir.

private void DropFile(object sender, DragEventArgs e)
 {
            string[] filePaths = e.Data.GetData(DataFormats.FileDrop) as string[];
            if (filePaths == null || filePaths.Count() == 0) { return; }

            CreateDropUserControls(CreateImage(GetFiles(filePaths)));
 }


Uygulamanın kaynak kodlarını buradan indirebilirsiniz




0 yorum:

Yorum Gönder