This walkthrough shows how to drag and drop an object, which is triggered from images that are bound to DragDrop event.
In this walkthrough, you perform the following tasks:
- Create a ClientUI MVVM Application project using Intersoft MVVM Application project template.
- Create the Model class that represents the Contact data entity.
- Create the View page that represents the user interface of the application.
- Create the ViewModel class that describes the View and provides the event to move the data source which is bound to the list box to another list box that defined in the View.
- Attach an event to UI controls in the View, such as the DragDrop event of the images and the ItemsSource property of the list box, to the ViewModel.
Prerequisites
You need the following components to complete this walkthrough:
- Visual Studio 2010
- Silverlight 4 Tools for Visual Studio 2010
- Intersoft ClientUI 2010
Creating a new ClientUI MVVM Application Project
The first step is to create a new ClientUI MVVM Application project using Intersoft ClientUI MVVM Application project template in Visual Studio.
To create the ClientUI MVVM Application project
- Start Visual Studio 2010.
- Create a new ClientUI MVVM Application project using Intersoft ClientUI MVVM Application project template. To learn more, see Walkthrough: Create New Intersoft ClientUI MVVM Application Template.
- In project reference, add System.Xml.Linq.dll. This assembly is required to perform LINQ query to xml data.
To add the data file
- In your project, create new folder with name Data.
- In Data folder, insert the data source from [Intersoft Installation Folder]\Intersoft WebUI Studio 2010 R1\Samples\SL4\ClientUI Samples\Intersoft.ClientUI.Samples.Assets\Data\ContactDataSource.xml.
- Click on the ContactDataSource.xml file and press F4 to open the Property Window. Change the Build Action property to Resources.
To add the resources file
- In your project, create new folder with name Assets.
- In Assets folder, create new folder with name Images.
- In Images folder, create new folder with name Photos.
- In Photos folder, copy the images from [Intersoft Installation Folder]\Intersoft WebUI Studio 2010 R1\Samples\SL4\ClientUI Samples\Intersoft.ClientUI.Samples.Assets\Images\Photos\].
Next, you will create the Contact model class that represent the data entity used in this walkthrough.
Creating Model Class
This section shows you how to create the Contact model class that represents the data entity used in this walkthrough. To create the Contact model class, see Walkthrough: Creating Model for Contact Data.
Next, you will create the view for your simple contacts list application.
Creating the View
This section steps you through the process of creating a page that uses a variety of ClientUI controls such as UXListBox. The UXListBox is used to display a collection of Contact data.
To create the View
- In your project, locate Views folder.
- In Views folder, add new UXPage with name Contact.xaml.
For more information on how to add a new item in Visual Studio, see Walkthrough: Add New Item such as Page, Dialog Box and Window in VS 2010 - Open Contact.xaml.
- Add a DockPanel. Set the VerticalAlignment and HorizontalAlignment property of DockPanel into Center.
- Add another DockPanel inside the previous DockPanel. Set the Width and Margin property of DockPanel into 270 and 4.
- Add the StylishLabel inside the DockPanel. Set the following properties of StylishLabel as below.
Properties Value Content Available Personnel Intersoft:DockPanel.Dock Top HorizontalContentAlignment Left - Add the UXSeparator. Set the Intersoft:DockPanel.Dock property of UXSeparator into Top.
- Add Grid. Set the Margin and Intersoft:DockPanel.IsFillElement property of Grid into 12 and True.
- Add the UXListBox inside the Grid. Set the following properties of UXListBox as below.
Properties Value Height 300 AllowDropItem True AllowMoveItem True AllowRemoveItem True HorizontalAlignment Stretch ItemContentType ContentAndImage ItemImageHeight 64 ItemImageWidth 64
XAML Copy Code
<Grid x:Name="LayoutRoot"> <Intersoft:DockPanel VerticalAlignment="Center" HorizontalAlignment="Center"> <Intersoft:DockPanel FillChildMode="Custom" Width="270" Margin="4"> <Intersoft:StylishLabel Content="Available Personnel" Intersoft:DockPanel.Dock="Top" HorizontalContentAlignment="Left"/> <Intersoft:UXSeparator Intersoft:DockPanel.Dock="Top"/> <Grid Margin="12" Intersoft:DockPanel.IsFillElement="True"> <Intersoft:UXListBox Name="uXListBox1" Height="300" AllowDropItem="True" AllowMoveItem="True" AllowRemoveItem="True" HorizontalAlignment="Stretch" ItemContentType="ContentAndImage" ItemImageHeight="64" ItemImageWidth="64" /> </Grid> </Intersoft:DockPanel> </Intersoft:DockPanel> </Grid>
- Repeat steps number 2-6. Set the Content property of StylishLabel into Out-Sourced Personnel.
XAML Copy Code
<Intersoft:DockPanel VerticalAlignment="Center" HorizontalAlignment="Center"> ... <Intersoft:DockPanel FillChildMode="Custom" Width="270" Margin="4"> <Intersoft:StylishLabel Content="Out-Sourced Personnel" Intersoft:DockPanel.Dock="Top" HorizontalContentAlignment="Left"/> <Intersoft:UXSeparator Intersoft:DockPanel.Dock="Top"/> <Grid Margin="12" Intersoft:DockPanel.IsFillElement="True"> <Intersoft:UXListBox Name="uXListBox2" Height="300" AllowDropItem="True" AllowMoveItem="True" AllowRemoveItem="True" HorizontalAlignment="Stretch" ItemContentType="ContentAndImage" ItemImageHeight="64" ItemImageWidth="64" /> </Grid> </Intersoft:DockPanel> </Intersoft:DockPanel>
Creating the ViewModel
In the previous sections, you have learned how to create the Model and ViewModel classes, as well as the View that contains the user interface and controls used in this walkthrough. This section shows how to instantiate the ViewModel in the XAML page and bind the UI elements to the properties in the ViewModel such as the items source and data context.
To create the ViewModel
- Add a new class to the ViewModels folder in your Silverlight project and name it ContactViewModel.cs.
- Open the ContactViewModel.cs and inherit the class from ViewModelBase class.
C# Copy Code
public class ContactViewModel : ViewModelBase { }
- In this view mode, you add the Contacts, ContactsData and OutsourceData which represent a collection of Contact.
C# Copy Code
// Fields private Contact _selectedItem = null; // Views public ObservableCollection<Contact> Contacts { get; set; } public ObservableCollection<Contact> ContactsData { get; set; } public ObservableCollection<Contact> OutsourceData { get; set; }
- Create a LoadData method to fill the Contact property based on the data from ContactDataSource.xml and invoke the method during object construction.
C# Copy Code
DragDropUXListBox public ContactViewModel() { this.LoadContacts(); } private void LoadContacts() { // loads contact data from xml file StreamResourceInfo resource = System.Windows.Application.GetResourceStream( new Uri("DragDropUXListBox;component/Assets/Data/ContactDataSource.xml", UriKind.Relative)); XDocument doc = XDocument.Load(resource.Stream); var contacts = from x in doc.Descendants("Customer") select new Contact(x); this.Contacts = new ObservableCollection<Contact>(); this.ContactsData = new ObservableCollection<Contact>(); this.OutsourceData = new ObservableCollection<Contact>(); foreach (Contact contact in contacts) { contact.SetPhoto(this.Contacts.Count.ToString()); this.Contacts.Add(contact); this.ContactsData.Add(contact); } resource.Stream.Close(); }
Binding The ViewModel Pattern to View Pattern
In the previous sections, you have learned how to create the Model and ViewModel classes, as well as the View that contains the user interface and controls used in this walkthrough. This section shows how to instantiate the ViewModel in the XAML page and bind the UI elements to the properties in the ViewModel such as the data context, template and event.
To bind the ViewModel pattern
- In MainPage.xaml, locate the UXPage.Resource under UXPage.
- Instantiate a new instance of the ContactViewModel class in the UXPage resources and name it ContactsData.
XAML Copy Code
<Intersoft:UXPage.Resources> <ViewModels:ContactViewModel x:Key="ContactsData"/> </Intersoft:UXPage.Resources>
- In MainPage.xaml, locate the Grid under DockPanel.
- Bind the DataContext property of each Grid inside the DockPanel to the ConstactsData through the static resource extension markup.
XAML Copy Code
<Intersoft:DockPanel FillChildMode="Custom" Width="270" Margin="4"> ... <Grid Margin="12" DataContext="{StaticResource ContactsData}" Intersoft:DockPanel.IsFillElement="True"> ... </Grid> </Intersoft:DockPanel>
- In MainPage.xaml, locate the UXListBox under the first DockPanel.
- Bind the ItemsSource property of the UXListBox to the ConstactsData through the binding extension markup such as shown in the following example.
XAML Copy Code
<Grid Margin="12" DataContext="{StaticResource ContactsData}" Intersoft:DockPanel.IsFillElement="True"> <Intersoft:UXListBox Name="uXListBox1" Height="300" AllowDropItem="True" AllowMoveItem="True" AllowRemoveItem="True" HorizontalAlignment="Stretch" ItemContentType="ContentAndImage" ItemImageHeight="64" ItemImageWidth="64" SelectedValuePath="Id" ItemsSource="{Binding ContactsData}" IsTextSearchEnabled="True" DisplayMemberPath="Name" ImageMemberPath="Photo" /> </Grid>
- In MainPage.xaml, locate the UXListBox under the second DockPanel.
- Bind the ItemsSource property of the second UXListBox to the OutsourceData through the binding extension markup such as shown in the following example.
XAML Copy Code
<Grid Margin="12" DataContext="{StaticResource ContactsData}" Intersoft:DockPanel.IsFillElement="True"> <Intersoft:UXListBox Name="uXListBox2" Height="300" AllowDropItem="True" AllowMoveItem="True" AllowRemoveItem="True" HorizontalAlignment="Stretch" ItemContentType="ContentAndImage" ItemImageHeight="64" ItemImageWidth="64" SelectedValuePath="Id" ItemsSource="{Binding OutsourceData}" IsTextSearchEnabled="True" DisplayMemberPath="Name" ImageMemberPath="Photo" /> </Grid>
- Run the project. Try to drag and drop the from Available list box into Out-sourced Personnel list box.
Conclusion
In this walkthrough, you have learned how to create ClientUI MVVM project using project template, and create the classes and page based on the Model, View and ViewModel pattern. You also learned how to bind UXListBox to a collection of data, and then Attach the UXListBox to a DragDrop event in the ViewModel which can move the object into another UXListBox.
Complete Code Listing
This section lists the complete code used in this walkthrough.
Contact.cs
C# | ![]() |
---|---|
using System; using System.Text.RegularExpressions; using System.Xml.Linq; using DragDropUXListBox.ViewModels; namespace DragDropUXListBox.Models { public class Contact : ModelBase { // rfc 2282 compliance email address regex private const string EmailPattern = @"[a-z0-9!#$&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"; #region Constructors public Contact() { } public Contact(XElement x) : this() { this._id = x.Element("Id").Value.Trim(); this._name = x.Element("Name").Value.Trim(); this._email = x.Element("Email").Value.Trim(); this._address = x.Element("Address").Value.Trim(); this._state = x.Element("State").Value.Trim(); this._zipCode = x.Element("ZipCode").Value.Trim(); this._phone = x.Element("Phone").Value.Trim(); this._fax = x.Element("Fax").Value.Trim(); this._cell = x.Element("Cell").Value.Trim(); this._blog = x.Element("Blog").Value.Trim(); this._twitter = x.Element("Twitter").Value.Trim(); this._website = x.Element("Website").Value.Trim(); } #endregion #region Fields private string _name = string.Empty; private string _address = string.Empty; private string _phone = string.Empty; private string _cell = string.Empty; private string _id = string.Empty; private string _email = string.Empty; private string _fax = string.Empty; private string _blog = string.Empty; private string _twitter = string.Empty; private string _website = string.Empty; private string _state = string.Empty; private string _zipCode = string.Empty; private Uri _photo = null; #endregion #region Properties public string Name { get { return this._name; } set { if (this._name != value) { this._name = value; this.ClearError("Name"); this.OnPropertyChanged("Name"); } } } public string Address { get { return this._address; } set { if (this._address != value) { this._address = value; this.ClearError("Address"); this.OnPropertyChanged("Address"); } } } public string Phone { get { return this._phone; } set { if (this._phone != value) { this._phone = value; this.OnPropertyChanged("Phone"); } } } public string Cell { get { return this._cell; } set { if (this._cell != value) { this._cell = value; this.OnPropertyChanged("Cell"); } } } public string Id { get { return this._id; } set { if (this._id != value) { this._id = value; this.OnPropertyChanged("Id"); } } } public string Email { get { return this._email; } set { if (this._email != value) { this._email = value; this.OnPropertyChanged("Email"); } } } public string Fax { get { return this._fax; } set { if (this._fax != value) { this._fax = value; this.OnPropertyChanged("Fax"); } } } public string Blog { get { return this._blog; } set { if (this._blog != value) { this._blog = value; this.OnPropertyChanged("Blog"); } } } public string Twitter { get { return this._twitter; } set { if (this._twitter != value) { this._twitter = value; this.OnPropertyChanged("Twitter"); } } } public string Website { get { return this._website; } set { if (this._website != value) { this._website = value; this.OnPropertyChanged("Website"); } } } public string State { get { return this._state; } set { if (this._state != value) { this._state = value; this.OnPropertyChanged("State"); } } } public string ZipCode { get { return this._zipCode; } set { if (this._zipCode != value) { this._zipCode = value; this.ClearError("ZipCode"); this.OnPropertyChanged("ZipCode"); } } } public Uri Photo { get { return this._photo; } set { if (this._photo != value) { this._photo = value; this.OnPropertyChanged("Photo"); } } } #endregion #region Methods public Contact Clone() { return new Contact() { Id = this._id, Name = this._name, Email = this._email, Address = this._address, State = this._state, ZipCode = this._zipCode, Phone = this._phone, Cell = this._cell, Fax = this._fax, Blog = this._blog, Twitter = this._twitter, Website = this._website, Photo = this._photo }; } public bool Validate(bool notifyDataError) { bool isValid = true; if (notifyDataError) this.ClearAllErrors(); if (string.IsNullOrEmpty(this.Id)) { isValid = false; if (notifyDataError) this.SetError("Id", "ID is required"); } if (string.IsNullOrEmpty(this.Name)) { isValid = false; if (notifyDataError) this.SetError("Name", "Please specify a name"); } if (string.IsNullOrEmpty(this.Email)) { isValid = false; if (notifyDataError) this.SetError("Email", "Please specify an email address"); } else { if (notifyDataError) { if (!Regex.IsMatch(this._email, Contact.EmailPattern)) this.SetError("Email", "Invalid email address"); } } if (string.IsNullOrEmpty(this.Phone)) { isValid = false; if (notifyDataError) this.SetError("Number", "Please specify a phone number"); } return isValid; } public void SetPhoto(string uri) { this.Photo = new Uri("/DragDropUXListBox;component/Assets/Images/" + uri + ".jpg", UriKind.RelativeOrAbsolute); } public void SetPhoto(Uri uri) { this.Photo = uri; } #endregion } } |
Contact.xaml
XAML | ![]() |
---|---|
<Intersoft:UXPage 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" xmlns:Intersoft="http://intersoft.clientui.com/schemas" xmlns:ViewModels="clr-namespace:DragDropUXListBox.ViewModels" mc:Ignorable="d" x:Class="DragDropUXListBox.Views.Contact" Title="Contact Page" d:DesignWidth="640" d:DesignHeight="480"> <Intersoft:UXPage.Resources> <ViewModels:ContactViewModel x:Key="ContactsData"/> </Intersoft:UXPage.Resources> <Grid x:Name="LayoutRoot"> <Intersoft:DockPanel VerticalAlignment="Center" HorizontalAlignment="Center"> <Intersoft:DockPanel FillChildMode="Custom" Width="270" Margin="4"> <Intersoft:StylishLabel Content="Available Personnel" Intersoft:DockPanel.Dock="Top" HorizontalContentAlignment="Left"/> <Intersoft:UXSeparator Intersoft:DockPanel.Dock="Top"/> <Grid Margin="12" DataContext="{StaticResource ContactsData}" Intersoft:DockPanel.IsFillElement="True"> <Intersoft:UXListBox Name="uXListBox1" Height="300" AllowDropItem="True" AllowMoveItem="True" AllowRemoveItem="True" HorizontalAlignment="Stretch" ItemContentType="ContentAndImage" ItemImageHeight="64" ItemImageWidth="64" SelectedValuePath="Id" ItemsSource="{Binding ContactsData}" IsTextSearchEnabled="True" DisplayMemberPath="Name" ImageMemberPath="Photo" /> </Grid> </Intersoft:DockPanel> <Intersoft:DockPanel FillChildMode="Custom" Width="270" Margin="4"> <Intersoft:StylishLabel Content="Out-Sourced Personnel" Intersoft:DockPanel.Dock="Top" HorizontalContentAlignment="Left"/> <Intersoft:UXSeparator Intersoft:DockPanel.Dock="Top"/> <Grid Margin="12" DataContext="{StaticResource ContactsData}" Intersoft:DockPanel.IsFillElement="True"> <Intersoft:UXListBox Name="uXListBox2" Height="300" AllowDropItem="True" AllowMoveItem="True" AllowRemoveItem="True" HorizontalAlignment="Stretch" ItemContentType="ContentAndImage" ItemImageHeight="64" ItemImageWidth="64" SelectedValuePath="Id" ItemsSource="{Binding OutsourceData}" IsTextSearchEnabled="True" DisplayMemberPath="Name" ImageMemberPath="Photo" /> </Grid> </Intersoft:DockPanel> </Intersoft:DockPanel> </Grid> </Intersoft:UXPage> |
ContactViewModel.cs
C# | ![]() |
---|---|
using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Intersoft.Client.Framework.Input; using System.Collections.ObjectModel; using System.Linq; using System.Windows.Resources; using System.Xml.Linq; using DragDropUXListBox.Models; namespace DragDropUXListBox.ViewModels { public class ContactViewModel : ViewModelBase { // Fields private Contact _selectedItem = null; // Views public ObservableCollection<Contact> Contacts { get; set; } public ObservableCollection<Contact> ContactsData { get; set; } public ObservableCollection<Contact> OutsourceData { get; set; } public string ContactsCount { get { if (this.Contacts.Count == 0) return "No contacts"; else if (this.Contacts.Count == 1) return "1 contact"; else return this.Contacts.Count + " contacts"; } } // Selection, View States public Contact SelectedItem { get { return _selectedItem; } set { if (_selectedItem != value) { _selectedItem = value; OnPropertyChanged("SelectedItem"); InvalidateCommands(); } } } public ContactViewModel() { this.LoadContacts(); } private void LoadContacts() { // loads contact data from xml file StreamResourceInfo resource = System.Windows.Application.GetResourceStream( new Uri("DragDropUXListBox;component/Assets/Data/ContactDataSource.xml", UriKind.Relative)); XDocument doc = XDocument.Load(resource.Stream); var contacts = from x in doc.Descendants("Customer") select new Contact(x); this.Contacts = new ObservableCollection<Contact>(); this.ContactsData = new ObservableCollection<Contact>(); this.OutsourceData = new ObservableCollection<Contact>(); foreach (Contact contact in contacts) { contact.SetPhoto(this.Contacts.Count.ToString()); this.Contacts.Add(contact); this.ContactsData.Add(contact); } resource.Stream.Close(); } protected virtual void InvalidateCommands() { } } } |