7. MainWindow Class
C#
7 / 58
private ObservableCollection<TodoItem> items = new ObservableCollection<TodoItem>();
public ObservableCollection<TodoItem> Items
{
get
{
return this.items;
}
}
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
private void OnAdd(object sender, RoutedEventArgs e)
{
string itemName = this.TextBox.Text;
this.items.Add(new TodoItem(itemName));
}
8. Design Patterns
• General reusable solution to a commonly occurring
problem within a given context
• Formalized best practices that the programmer
must implement themselves in the application
• Not a finished design that can be transformed directly
into source code
• Gained popularity in computer science after the
book Design Patterns: Elements of Reusable Object-
Oriented Software was published in 1994 by the so-
called "Gang of Four" (Gamma et al.)
8 / 78
9. Advantages of
Design Patterns
• Speed up the development process by providing
tested, proven development paradigms
• Improve code readability for coders and architects
who are familiar with the patterns
9 / 78
11. Object-Oriented Design 101
• Aggregation
• Combine simple objects or data types into more
complex ones
• Usually expressed by means of references from one
object to another
• Inheritance
• Adding detail to a general data type to create a more
specific data type
11 / 78
12. Object-Oriented Design 101
• Delegation
• Handing a task over to another part of the program
• Polymorphism
• Ad hoc polymorphism (function overloading)
• Parametric polymorphism (generic programming)
• Subtyping (subclassing)
12 / 78
13. Object-Oriented Design 101
• Cohesion
• Degree to which the elements of a module belong
together
• How much functionalities embedded in a class have in
common
• Coupling
• Degree to which each program module relies on the
other modules
13 / 78
14. Object-Oriented Design 101
• Cohesion
• Degree to which the elements of a module belong
together
• How much functionalities embedded in a class have in
common
• Coupling
• Degree to which each program module relies on the
other modules
14 / 78
22. MainWindow Class
C#
22 / 58
private void OnRedo(object sender, RoutedEventArgs e)
{
if (redoStack.Count < 1)
{
return;
}
// Move memento from Redo to Undo stack.
Memento memento = redoStack.Pop();
undoStack.Push(memento);
// Restore previous state.
this.RestoreFromMemento(memento);
}
23. Command Pattern
Encapsulates all the information needed to
call a method at a later time in an object.
23 / 78
Examples:
• Networking
• Replays
• AI
• Undo
27. AddItemCommand Class
C#
27 / 58
public class AddItemCommand : ICommand
{
private ObservableCollection<TodoItem> items;
private string newItemName;
public AddItemCommand(ObservableCollection<TodoItem> items, string newItemName)
{
this.items = items;
this.newItemName = newItemName;
}
public void DoCommand()
{
TodoItem todoItem = new TodoItem(this.newItemName);
this.items.Add(todoItem);
}
public void UndoCommand()
{
TodoItem todoItem = this.items.First(item => item.ItemName.Equals(this.newItemName));
this.items.Remove(todoItem);
}
}
28. MainWindow Class
C#
28 / 58
private Stack<ICommand> undoStack = new Stack<ICommand>();
private Stack<ICommand> redoStack = new Stack<ICommand>();
private void OnAdd(object sender, RoutedEventArgs e)
{
// Add new item.
var itemName = this.TextBox.Text;
AddItemCommand command = new AddItemCommand(this.items, itemName);
command.DoCommand();
// Save command and clear Redo stack.
this.undoStack.Push(command);
this.redoStack.Clear();
}
29. MainWindow Class
C#
29 / 58
private void OnUndo(object sender, RoutedEventArgs e)
{
if (undoStack.Count < 1)
{
return;
}
// Move command from Undo to Redo stack.
ICommand command = undoStack.Pop();
redoStack.Push(command);
// Undo command.
command.UndoCommand();
}
30. MainWindow Class
C#
30 / 58
private void OnRedo(object sender, RoutedEventArgs e)
{
if (redoStack.Count < 1)
{
return;
}
// Move command from Redo to Undo stack.
ICommand command = redoStack.Pop();
undoStack.Push(command);
// Redo command.
command.DoCommand();
}
31. Drag & Drop
• Commonly refers to a method of data transfer that
involves using a mouse (or some other pointing
device) to
• select one or more objects,
• dragging these objects over some desired drop target in
the user interface (UI),
• and dropping them.
31 / 58
32. Drag & Drop in WPF
• Drag-and-drop operations typically involve two
parties:
• drag source from which the dragged object originates
• drop target which receives the dropped object
• Drag source and drop target may be UI elements in
the same application or a different application.
32 / 58
33. Drag & Drop in WPF
• The type and number of objects that can be
manipulated with drag-and-drop is completely
arbitrary.
• Files
• Folders
• Content
• The particular actions performed during a drag-
and-drop operation are application-specific, and
often determined by context.
33 / 58
34. Drag & Drop Data Transfer
• Dragging and dropping items requires a way to
temporarily store the transferred data.
• WPF uses a DataObject to store the data:
• The drag source initiates a drag-and-drop operation,
passing the transferred data to it.
• Any serializable object can be passed. If the data is not
already wrapped in a DataObject, it will automatically
be wrapped in a new DataObject.
• For greater control over the data format, you can wrap
the data in a DataObject yourself.
• The drop target is responsible for extracting the data
from the DataObject.
34 / 58
35. Drag & Drop Effects
• Data that is actually being transferred typically does not
have a visual representation.
• By default, feedback is provided to the user by changing the
cursor to represent the effect that the drag-and-drop
operation will have on the data, such as whether the data
will be moved or copied.
• WPF defines a DragDropEffects enumeration that you can
use to specify the effect of a drag-and-drop operation.
• It is important to remember that in WPF, the actual effect of
the drag-and-drop operation depends on you to write the
appropriate code in your application.
• For example, the drop target might specify that the effect of
dropping data on it is to move the data.
• However, to move the data, it must be both added to the target
element and removed from the source element.
35 / 58
36. Implementing Drag & Drop
1. Drag Source
1. Identify the element that will be a drag source. A drag
source can be a UIElement or a ContentElement.
2. Create an event handler on the drag source that will
initiate the drag-and-drop operation. The event is
typically the MouseMove event.
3. In the drag source event handler, call
the DoDragDrop method to initiate the drag-and-drop
operation. In the DoDragDrop call, specify the drag
source, the data to be transferred, and the allowed
effects.
36 / 58
37. Implementing Drag & Drop
2. Drop Target
1. Identify the element that will be a drop target. A drop
target can be UIElement or a ContentElement.
2. On the drop target, set the AllowDrop property to true.
3. In the drop target, create a Drop event handler to process
the dropped data.
4. In the Drop event handler, extract the data from
the DragEventArgs by using
the GetDataPresent and GetData methods.
5. In the Drop event handler, use the data to perform the
desired drag-and-drop operation.
37 / 58
38. Drag & Drop
Sample Application
• Data
• List of To-do items – Today
• List of To-do items – Tomorrow
• Operations
• Move To-Do item from today to tomorrow
38 / 58
40. MainWindow Class
C#
40 / 58
private ObservableCollection<TodoItem> today = new ObservableCollection<TodoItem>();
private ObservableCollection<TodoItem> tomorrow = new ObservableCollection<TodoItem>();
public ObservableCollection<TodoItem> Today
{
get { return this.today; }
}
public ObservableCollection<TodoItem> Tomorrow
{
get { return this.tomorrow; }
}
public MainWindow()
{
InitializeComponent();
DataContext = this;
this.today.Add(new TodoItem("Wash the dishes"));
this.today.Add(new TodoItem("Clean up the closet"));
this.tomorrow.Add(new TodoItem("Buy new pizza"));
this.tomorrow.Add(new TodoItem("Prepare next lecture"));
}
41. MainWindow Class
C#
41 / 58
private void UIElement_OnMouseMove(object sender, MouseEventArgs e)
{
ListBox listBox = (ListBox)sender;
TodoItem selectedItem = (TodoItem)listBox.SelectedItem;
if (e.LeftButton == MouseButtonState.Pressed)
{
// Prepare data to be transferred.
DragDrop.DoDragDrop(listBox, selectedItem.ItemName, DragDropEffects.Move);
}
}
42. MainWindow Class
C#
42 / 58
private void UIElement_OnDragOver(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.None;
// Check if any data is present.
if (e.Data.GetDataPresent(DataFormats.StringFormat))
{
// Check if the data is valid for our to-do list.
string dataString = (string)e.Data.GetData(DataFormats.StringFormat);
if (this.CheckData(dataString))
{
// Change drag & drop effect
e.Effects = DragDropEffects.Copy | DragDropEffects.Move;
}
}
}
43. MainWindow Class
C#
43 / 58
private void UIElement_OnDrop(object sender, DragEventArgs e)
{
ListBox listBox = (ListBox)sender;
if (listBox != null)
{
// Check if any data is present.
if (e.Data.GetDataPresent(DataFormats.StringFormat))
{
// Check if the data is valid for our to-do list.
string dataString = (string)e.Data.GetData(DataFormats.StringFormat);
if (this.CheckData(dataString))
{
// Move to-do list item from today to tomorrow.
TodoItem todoItem = today.First(item => item.ItemName.Equals(dataString));
today.Remove(todoItem);
tomorrow.Add(todoItem);
}
}
}
}
44. Enhanced Drag & Drop
To transfer custom data or multiple data items,
create a DataObject to pass to the DoDragDrop
method:
string stringData = "Some string data to store...";
string dataFormat = DataFormats.UnicodeText;
DataObject dataObject = new DataObject(dataFormat, stringData);
44 / 58
45. Drag & Drop Data Formats
45 / 58
Field Field Value Description
Bitmap "Bitmap" Specifies a Microsoft Windows bitmap data format.
CommaSeparatedValue "CSV" Specifies a comma-separated value (CSV) data format.
Dib "DeviceIndependentBitmap" Specifies the device-independent bitmap (DIB) data
format.
Dif "DataInterchangeFormat" Specifies the Windows Data Interchange Format (DIF)
data format.
EnhancedMetafile "EnhancedMetafile" Specifies the Windows enhanced metafile format.
FileDrop "FileDrop" Specifies the Windows file drop format.
Html "HTML Format" Specifies the HTML data format.
Locale "Locale" Specifies the Windows locale (culture) data format.
MetafilePicture "MetaFilePict" Specifies the Windows metafile picture data format.
OemText "OEMText" Specifies the standard Windows OEM text data format.
46. Drag & Drop Data Formats
46 / 58
Field Field Value Description
Palette "Palette" Specifies the Windows palette data format.
PenData "PenData" Specifies the Windows pen data format.
Riff "RiffAudio" Specifies the Resource Interchange File Format (RIFF) audio data
format.
Rtf "Rich Text Format" Specifies the Rich Text Format (RTF) data format.
Serializable "PersistentObject" Specifies a data format that encapsulates any type of serializable
data objects.
StringFormat "System.String" Specifies the common language runtime (CLR) string class data
format.
SymbolicLink "SymbolicLink" Specifies the Windows symbolic link data format.
Text "Text" Specifies the ANSI text data format.
Tiff "TaggedImageFileFormat" Specifies the Tagged Image File Format (TIFF) data format.
UnicodeText "UnicodeText" Specifies the Unicode text data format.
WaveAudio "WaveAudio" Specifies the wave audio data format.
Xaml "Xaml" Specifies the Extensible Application Markup Language (XAML) data
format.
XamlPackage "XamlPackage" Specifies the Extensible Application Markup Language (XAML)
package data format.
47. Drag & Drop Preview
• DragEnter event is raised once each time an object
is dragged into the bounds of an element that is
acting as a drop target.
• Handle this event to provide a preview of the effects of
the drag-and-drop operation, if appropriate for your
application.
• DragLeave event occurs when the data is dragged
out of the target's boundary without being
dropped.
• Handle this event to undo anything that you did in
the DragEnter event handler.
47 / 58
48. Drag & Drop Feedback
• GiveFeedback event is raised continuously while
the drag source is being dragged.
• Handle this event if you need to use custom cursors to
provide feedback to the user.
• Default handler for this event checks whether the drag
source is over a valid drop target.
48 / 58
49. Cancel Drag & Drop
• QueryContinueDrag event is raised continuously
while the drag source is being dragged.
• Handle this event to determine what action ends the
drag-and-drop operation based on the state of the ESC,
SHIFT, CTRL, and ALT keys, as well as the state of the
mouse buttons.
• Default handler for this event cancels the drag-and-drop
operation if the ESC key is pressed, and drops the data if
the mouse button is released.
49 / 58
50. Assignment #7
Undo & Redo
1. Add menu items and toolbar buttons for Undo and
Redo to your main window.
2. Use the Command pattern to add undo and redo for
drawing map tiles to your application.
3. A single undo or redo should affect all map tiles
drawn with a single click.
4. Both the undo and redo stacks should be cleared
when creating a new map or loading an existing one.
5. Both operations should only be available if the
respective stacks are not empty.
50 / 58
51. References
• Paul. Multilevel Undo and Redo Implementation in
C#.
http://www.codeproject.com/Articles/33384/Multi
level-Undo-and-Redo-Implementation-in-C-Part,
February 17, 2009.
• MSDN. Drag and Drop Overview.
https://msdn.microsoft.com/de-
de/library/ms742859(v=vs.110).aspx, May 2016.
51 / 58
53. 5 Minute Review Session
• What are the main advantages of design patterns?
• Which types of design patterns do you know?
• What’s the difference between inheritance and
aggregation?
• Which types of polymorphism do you know?
• What’s the difference between cohesion and coupling?
• Which design patterns can be used for implementing an
undo-redo stack?
• Which parties are typically involved in drag-and-drop
operations?
• How do you tell the user about the effect that the drag-and-
drop operation will have on the data?
53 / 58