Click here to Skip to main content
15,884,425 members
Articles / Desktop Programming / WPF

DraggableListView - Adding drag-to-scroll functionality to ListView in WPF

Rate me:
Please Sign up or sign in to vote.
4.88/5 (13 votes)
3 Oct 2008CPOL4 min read 104.1K   4.8K   43  
A custom ListView that scrolls when its contents are dragged on screen.
using System;
using System.Collections.Generic;
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.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;

namespace DraggableListViewSample
{
    /// <summary>
    /// Interaction logic for EditableListView.xaml
    /// </summary>

    public partial class EditableListView : System.Windows.Controls.Page
    {

        private IEditableCollectionView iecv;
        private CollectionView cv;


        public EditableListView()
        {
            InitializeComponent();
            // retrieve a reference to the view
            ICollectionView view = CollectionViewSource.GetDefaultView(itemsList.Items);
            iecv = (IEditableCollectionView)view;
            cv = (CollectionView)view;

            iecv.NewItemPlaceholderPosition = NewItemPlaceholderPosition.None;
            itemsList.PreviewKeyUp += new KeyEventHandler(itemsList_PreviewKeyUp);
        }

        void DeleteItem(object sender, RoutedEventArgs e)
        {
            ListViewItem item = itemsList.ItemContainerGenerator.ContainerFromIndex(itemsList.SelectedIndex) as ListViewItem;
            if (item != null)
            {
                if (iecv.IsEditingItem)
                {
                    iecv.CommitEdit();
                }
                else
                    if (iecv.IsAddingNew)
                    {
                        iecv.CommitNew();
                    }

                // remove the item here
                iecv.Remove(itemsList.SelectedItem);
                itemsList.UpdateLayout();
            }

        }

        void AddItem(object sender, RoutedEventArgs e)
        {

            if (!iecv.CanAddNew)
            {
                return;
            }

            ListViewItem item = itemsList.ItemContainerGenerator.ContainerFromIndex(itemsList.SelectedIndex) as ListViewItem;
            if (item != null)
            {
                // add the item and update the layout
                object newItem = iecv.AddNew();
                this.itemsList.UpdateLayout();

                itemsList.ScrollIntoView(newItem);
                // update the template
                ListViewItem lbItem = (ListViewItem)itemsList.ItemContainerGenerator.ContainerFromItem(iecv.CurrentAddItem);
                lbItem.ContentTemplate = (DataTemplate)this.myGrid.FindResource("EditTemplate");
                btnAddItem.IsEnabled = false;
                btnCancelEdit.IsEnabled = true;
            }
        }

        private void CancelEdit(object sender, RoutedEventArgs e)
        {
            CancelOperation();
        }

        void itemsList_PreviewKeyUp(object sender, KeyEventArgs e)
        {

            if (e.Key == Key.Escape)
            {
                CancelOperation();

            }
        }

        private void CancelOperation()
        {
            ListViewItem lbItem = null;
            if (iecv.IsEditingItem)
            {
                lbItem = (ListViewItem)itemsList.ItemContainerGenerator.ContainerFromItem(iecv.CurrentEditItem);
                iecv.CancelEdit();
            }
            else if (iecv.IsAddingNew)
            {
                lbItem = (ListViewItem)itemsList.ItemContainerGenerator.ContainerFromItem(iecv.CurrentAddItem);
                iecv.CancelNew();
                iecv.CommitEdit();
            }
            if (lbItem != null)
            {
                lbItem.ContentTemplate = (DataTemplate)this.myGrid.FindResource("DefaultTemplate");
                btnAddItem.IsEnabled = true;
                btnCancelEdit.IsEnabled = false;
            }
        }

        private void itemsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

            if (iecv != null && iecv.IsEditingItem)
            {
                ListViewItem lbItem = (ListViewItem)itemsList.ItemContainerGenerator.ContainerFromItem(iecv.CurrentEditItem);
                iecv.CommitEdit();

                // update the template
                lbItem.ContentTemplate = (DataTemplate)this.myGrid.FindResource("DefaultTemplate");
                btnAddItem.IsEnabled = true;
                btnCancelEdit.IsEnabled = false;
            }

            if (iecv != null && itemsList.SelectedItem != null && !iecv.IsAddingNew)
            {

                // edit the item
                iecv.EditItem(itemsList.SelectedItem);

                // update the template
                ListViewItem lbItem = (ListViewItem)itemsList.ItemContainerGenerator.ContainerFromItem(iecv.CurrentEditItem);
                lbItem.ContentTemplate = (DataTemplate)this.myGrid.FindResource("EditTemplate");
                btnAddItem.IsEnabled = false;
                btnCancelEdit.IsEnabled = true;

            }
            else
                if (iecv != null && iecv.IsAddingNew && itemsList.SelectedItem != null)
                {
                    ListViewItem lbItem = (ListViewItem)itemsList.ItemContainerGenerator.ContainerFromItem(iecv.CurrentAddItem);
                    if (lbItem != null)
                    {
                        iecv.CommitNew();

                        // update the template
                        lbItem.ContentTemplate = (DataTemplate)this.myGrid.FindResource("DefaultTemplate");
                        btnAddItem.IsEnabled = true;
                        btnCancelEdit.IsEnabled = false;
                    }
                }
        }
    }

    #region Data Source

    public class FileData : INotifyPropertyChanged, IEditableObject
    {

        private FileData localCopy = null;


        public FileData()
            : this("tempFile", DateTime.Now)
        {
            localCopy = null;
        }

        public FileData(string fileName, DateTime creationTime)
        {
            FileName = fileName;
            FileCreationTime = creationTime;
        }

        #region Properties

        private string fileName;
        private DateTime creationTime;


        public string FileName
        {
            get { return fileName; }
            set { fileName = value; }
        }


        public DateTime FileCreationTime
        {
            get { return creationTime; }
            set { creationTime = value; }
        }

        #endregion Properties

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region IEditableObject Members

        void IEditableObject.BeginEdit()
        {
            if (localCopy == null)
            {
                localCopy = new FileData();
            }

            localCopy.FileName = this.FileName;
            localCopy.FileCreationTime = this.FileCreationTime;
        }

        void IEditableObject.CancelEdit()
        {
            this.FileName = localCopy.FileName;
            this.FileCreationTime = localCopy.FileCreationTime;

            localCopy = null;
        }

        void IEditableObject.EndEdit()
        {
            localCopy = null;
        }

        #endregion
    }

    public class Files : ObservableCollection<FileData>
    {
        public Files()
        {

            foreach (string filePath in Directory.GetFiles("c:\\windows\\system32"))
            {
                DateTime creationTime = File.GetCreationTime(filePath);
                Add(new FileData(filePath, creationTime));
            }
        }
    }

    #endregion Data Source
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Weidong has been an information system professional since 1990. He has a Master's degree in Computer Science, and is currently a MCSD .NET

Comments and Discussions