CS411handoutbyvirtualians PK
CS411handoutbyvirtualians PK
Contents
1 Lecture 1
2 Lecture 2
3 Lecture 3
13
4 Lecture 4
17
5 Lecture 5
21
6 Lecture 6
27
7 Lecture 7
35
8 Lecture 8
43
9 Lecture 9
47
10 Lecture 10
53
11 Lecture 11
61
12 Lecture 12
69
13 Lecture 13
71
14 Lecture 14
75
15 Lecture 15
77
16 Lecture 16
83
17 Lecture 17
89
18 Lecture 18
95
19 Lecture 19
101
20 Lecture 20
107
21 Lecture 21
111
22 Lecture 22
119
23 Lecture 23
123
3
CONTENTS
24 Lecture 24
129
25 Lecture 25
133
26 Lecture 26
137
27 Lecture 27
141
28 Lecture 28
145
29 Lecture 29
151
30 Lecture 30
157
31 Lecture 31
163
32 Lecture 32
169
33 Lecture 33
173
34 Lecture 34
177
35 Lecture 35
183
36 Lecture 36
189
37 Lecture 37
195
38 Lecture 38
201
39 Lecture 39
205
40 Lecture 40
211
41 Lecture 41
217
42 Lecture 42
223
43 Lecture 43
233
44 Lecture 44
241
45 Lecture 45
253
Chapter 1
Lecture 1
This course is about graphical user interfaces and the event-driven model as applied to desktop, web, and mobile
applications. It uses a ground up approach from what you already know.
The pre-requisites are C++ programming and data structures. I will introduce any new languages and concepts
we are going to use.
This is a hands-on course. We will use in-class examples and you should focus on completing programming
assignments to understand the material.
We will primarily use 2 books in this course. Event processing in action and Windows presentation foundation
unleashed. The first one is authored by Opher Etzion and Peter Niblett and is one of the very few books on event
processing. Event processing is often taught as a side-concept, but we will focus on it in this course. The other book
is by Adam Nathan. It is about Windows presentation foundation or WPF in short. We use it as our gui example
with C#. We will introduce C# concepts and WPF concepts. They are not a pre-requisite for this course.
Later in the course, we will touch event-driven programming in the browser, in particular made possible by techniques called AJAX. Again not a pre-requisite. I will introduce all the concepts in class.
Towards the very end, we will discuss event driven programming on mobiles. Again no pre-requisite. I will introduce
all the tools involved.
So what is Visual Programming and what you will learn in this course. Its primarily event driven concepts and
application of these concepts on GUI programs on desktop, web, and mobile.
Here is our first example:
1
2
3
4
5
6
7
8
9
10
11
6
6
7
8
9
10
11
12
13
14
15
CHAPTER 1. LECTURE 1
do {
std :: ifstream f (" test . txt " , std :: ifstream :: in );
if ( f . good () && a != f . peek ()) {
a = f . get ();
std :: cout << a << std :: endl ;
}
f . close ();
} while ( a != x );
return 0;
}
Lets compile and run it. There are a few issues like busy wait etc. but well leave them on a side for now.
So why we saw these two very basic examples. Well, they were both very easy to write. Can we combine them
with an OR. i.e. we react to either of the two actions. Here is how we can do it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int onKeyPress ()
{
char b = std :: cin . get ();
std :: cout << b << std :: endl ;
return b == x ;
}
int onFileChanged ()
{
char a = f . get ();
std :: cout << a << std :: endl ;
return a == x ;
}
int main ()
{
char a = -, b ;
do {
if ( IsKeyboardPressed ()) {
if ( onKeyPress ())
return 0;
}
std :: ifstream f (" test . txt " , std :: ifstream :: in );
if ( f . good () && a != f . peek ()) {
if ( onFileChanged ())
7
24
25
26
27
28
29
return 0;
}
f . close ();
} while ( true );
return 0;
}
So what are the pros and cons of the re-factored approach. We do one thing at a time (more focused approach).
Blocking is a huge issue. Nothing is parallel. The key idea is that once you understand the approach, it scales really
well to a large number of things you want to respond to.
Next time well define events, event loops, and dierent terms in the event driven model.
CHAPTER 1. LECTURE 1
Chapter 2
Lecture 2
Last time, we saw some examples and demonstrated the idea of event driven design.
We can re-factor the last example even one step further like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
10
41
42
43
CHAPTER 2. LECTURE 2
} while ( true );
return 0;
}
So what is an event. Its an occurrence within a particular system or domain. There are two meanings: something
that happened and the corresponding detection in computer world. An event captures some things from the actual
occurrence and multiple events may capture one occurrence.
Probabilistic events may or may not relate to an actual occurrence e.g. a fraud detection event on a banking
transaction. Every event is represented by an event-object. There are various types of events and information in the
event describes details of the particular event type. e.g. key press, file event etc.
Lets take a coee shop analogy. Events are taking place all the time. Lets understand synchronous and asynchronous
behavior with this example. So if an order is completed, coee ready, pastery heated before the next order thats
synchronous behavior. There are observed events and deduced events. Situation is an event ocurrence that requires a
reaction.
Lets take example of events in computing systems. Interrupts and exceptions on a computer e.g. divide by zero.
Patient monitored by sensors. Car sensors alerting to oil or pressure situations. Banking alerts. Road tolling. etc.
Event processing is computing that performs operations on events. Common event processing operations include
reading, creating, transforming, and deleting events. The design, coding and operation of applications that use events,
either directly or indirectly is called event-based programming or applications based on event-driven architecture.
So what if we dont use event-driven programming. We will poll for events. Even if you make your application
non-event-driven, you still wait for events. Wait for a single event is blocking operation.
Synchronous operations are completed before the next operation can be started. Asynchronous operations can be
started and we can do something else before they are completed.
Why do we want our applications to be event based. They are easier to scale. Well suited to Visual programming
where multiple GUI elements and many sources of events exist. It has a direct mapping to real world. Its deterministic
there is an exact mapping between a situation in the real world and its representation in the event processing system.
At the same time its approximatethe event processing system provides an approximation to real world events.
So what kind of events are there in non-real time applications. Mouse and keyboard, secondary events of GUI
elements, file events, message based parallel and local communication, network events etc.
Here is flower delivery example from the book.
Here are some excerpts of its description from the book. A consortium of flower stores in a large city has established
an agreement with local independent van drivers to deliver flowers from the stores to their destinations. When a store
gets a flower delivery order, it creates a request which is broadcast to relevant drivers within a certain distance from
the store, with the time for pickup (typically now) and the required delivery time. A driver is then assigned and the
customer is notified that a delivery has been scheduled. The driver makes the pickup and delivery, and the person
receiving the flowers confirms the delivery time by signing for it on the drivers mobile device. The system maintains
a ranking of each individual driver based on his or her ability to deliver flowers on time. Each store has a profile that
can include a constraint on the ranking of its drivers; for example, a store can require its drivers to have a ranking
11
greater than 10. The profile also indicates whether the store wants the system to assign drivers automatically, or
whether it wants to receive several applications and then make its own choice. A permanently weak driver is a driver
with fewer than five assignments on all the days on which the driver has been active. An idle driver is a driver with
at least one day of activity that had no assignments. A consistently weak driver is a driver whose assignments, when
active, are at least two standard deviations lower than the average assignments per driver on that day. A consistently
strong driver is a driver whose daily assignments are at least two standard deviations higher than the average number
of assignments per driver on each day in question. An improving driver is a driver whose assignments increase or stay
the same day by day.
12
CHAPTER 2. LECTURE 2
Chapter 3
Lecture 3
Lets discuss request and response based applications. Example is a web browser which sends queries and updates. It
performs synchronous interactions. It looks like this:
Events are based on the principle of decoupling. Lets compare events and request-response based architecture.
Events have already happened whereas requests are asking something to happen. Service requester or client contacts
the service provider or the server. In event-driven architecture event producer sends event to event consumer. A
customer order can be respresented as an event or a request: what are the benefits of each approach?
Similarly, should we send a request to query the state or use change events. Event has meaning independent of
its producers and consumers whereas the same cannot be said about requests. Events are often one way (push events).
Events decouple producers and consumers. Events can be processed asynchronously. There can be more than one
consumer, each processing it dierently possibly processing a sequence of events that happened over time. Latency is
reduced in comparison to the pull style.
Events can also be compared to messages. Messages may contain events. Events may live outside events like in
event logs.
An event channel is a subscription mechanism for events. It further decouples consumers and producers. Can even
be an intermediate XML file to store events.
Event-driven architecture and service-driven architecture can also be compared. Event-based programming, also
called event-driven architecture (EDA) is an architectural style in which one or more components in a software system
execute in response to receiving one or more event notifications. Service-oriented architecture (SOA) is built from
request-response. It moves away from monolithic applications. There are many similarities and often a component
can provide both modes of contacting it.
Here are some definitions from the book.
13
14
CHAPTER 3. LECTURE 3
EVENT PRODUCER: An event producer is an entity at the edge of an event process- ing system that introduces
events into the system.
EVENT CONSUMER: An event consumer is an entity at the edge of an event pro- cessing system that receives
events from the system.
RAW EVENT: A raw event is an event that is introduced into an event processing system by an event producer.
DERIVED EVENT: A derived event is an event that is generated as a result of event processing that takes place
inside an event processing system.
STATELESS EVENT PROCESSING An event processing agent is said to be stateless if the way it processes one
event does not influence the way it processes any subsequent events.
EVENT STREAM An event stream (or stream) is a set of associated events. It is often a temporally totally ordered
set (that is to say, there is a well-defined timestamp-based order to the events in the stream). A stream in which all
the events must be of the same type is called a homogeneous event stream; a stream in which the events may be of
dierent types is referred to as a heterogeneous event stream.
Here are types of event agents.
Looking back at the program discussed before, can you map the event definitions to the code below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
15
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
What aspects of real occurrence do event objects capture. An event type is a specification for a set of event objects
that have the same semantic intent and same structure; every event object is considered to be an instance of an event
type.
An event attribute is a component of the structure of an event. Each attribute has a name and a data type. It can
also have occurrence/detection time, certainty, source, location. Events can be composed, generalized, and specialized.
Lets experiment with flower delivery example. Can you find events and their attributes.
Event producers can produce events that are hardware generated, software generated, or from human interaction.
Event consumers have similar types. Examples are locking or unlocking a door, raising or lowering a barrier, applying
the brakes on a vehicle, opening or closing a valve, controlling a railroad switch, and turning a piece of equipment on
or o. Try to find producers and consumers in flower delivery application.
16
CHAPTER 3. LECTURE 3
Chapter 4
Lecture 4
We will get introduced to C# in this lecture. Before that, lets start with some history of Java and J++. Microsoft
wanted to extend Java to communicate it with COM. Sun did not want that as it would make Java platform dependent.
Microsoft wanted a clean-room implementation of Java. What is a clean-room implementation?
Clean room design (also known as the Chinese wall technique) is the method of copying a design by reverse
engineering and then recreating it without infringing any of the copyrights and trade secrets associated with the
original design. Clean room design is useful as a defense against copyright and trade secret infringement because it
relies on independent invention. However, because independent invention is not a defense against patents, clean room
designs typically cannot be used to circumvent patent restrictions.
Where do the name for C# comes from. The initial name was Cool, which stood for C-like Object Oriented
Language. Whats the dierence between .NET and C#. C# design most directly reflects .NET (CLR) design but
C# is a language and .NET is the platform.
As a first step, you should get Visual Studio from http://www.microsoft.com/visualstudio. Click Downloads and
choose Visual Studio Express 2012 for Windows Desktop. Choose Download now or Install now. You can save
iso file to disk (right click to mount in win8) otherwise there are free utilities to mount it or burn it on a cd.
Install and register online for continued use. To create a new project choose File, New Project, Visual C#, Console
Application. Then click the Start key.
Here are some notable features of C#.
No global variables or functions.
Locals cannot shadow global variables.
There is a strict boolean type.
Memory address pointers can only be used in specifically marked unsafe blocks and require permissions
No instruction to free memory. Only garbage collection.
Try-finally block.
No multiple inheritance but interfaces supported.
Operator overloading allowed.
More type-safe (only integer widening allowed).
Enumeration members are scoped.
Property syntax for getters and setters.
No checked exceptions.
some functional programming features like function objects and lambda expressions.
17
18
CHAPTER 4. LECTURE 4
The common type system of C# has value types and reference types. Instances of value types do not have
referential identity nor referential comparison semantics. Value types are derived from System.ValueType and can
always be created, copied and have a default value (int, float, char, System.DateTime, enum, struct). In contrast,
reference types have the notion of referential identity. Default equality and inequality comparisons test for referential
rather than structural equality unless overloaded e.g System.String. Not always possible to create an instance
of a reference type, copy an existing instance, perform a value comparison on two instances, though specific types
can provide such services by exposing a public constructor or implementing a corresponding interface e.g. object,
System.String, System.Array.
Here is how to box and unbox variables in C#. Boxing stores a value type in a reference type.
1
2
3
// Value type .
// foo is boxed to bar .
// Unboxed back to value type .
Pre-processor directives like #if, #else, #endif, #region, #endregion are supported. Comments are written using
// and /* */. It also provides an XML documentation system that is used like this.
1
2
3
4
5
6
The C# specification details a minimum set of types and class libraries that the compiler expects to have available.
In practice, C# is most often used with some implementation of the Common Language Infrastructure (CLI), which
is standardized as ECMA-335 Common Language Infrastructure (CLI).
Here is a hello world program in C#.
1
2
3
4
5
6
using System ;
class Program {
static void Main () {
Console . WriteLine (" Hello world !");
}
}
Writing the using clause uses System as a candidate prefix for types used in the source code. when the compiler
sees use of the Console type later in the source code. It allows the programmer to state all candidate prefixes to use
during compilation instead of always using full type names. Console is a static class in the System namespace.
If you run the program from within Visual Studio and the console window disappears quickly you can use the
following code.
1
2
3
away
19
To test use csc.exe Welcome.cs or run from within Visual Studio.
Now lets write a GUI based hello world.
1
2
3
4
5
6
7
8
9
// Namespace Declaration
using System ;
// Program start class
class Inte ra ct iv eW el com e
{
// Main begins program execution .
public static void Main ()
{
// Write to console / get input
Console . Write (" What is your name ?: ");
Console . Write (" Hello , {0}! " , Console . ReadLine ());
Console . WriteLine (" Welcome to the C \# Station Tutorial !");
}
}
20
CHAPTER 4. LECTURE 4
Chapter 5
Lecture 5
Here is an example with boolean types.
1
2
3
4
5
6
7
8
9
10
11
12
13
using System ;
class Booleans
{
public static void Main ()
{
bool content = true ;
bool noContent = false ;
Console . WriteLine (" It is {0} that C \# Station provides C \# programming language content ." , conte
Console . WriteLine (" The statement above is not {0}." , noContent );
}
}
And here are the floating point and decimal types in C#.
22
CHAPTER 5. LECTURE 5
The escape character is while @ is the verbatim character. The following operators are supported by C#.
using System ;
class Array {
public static void Main (){
int [] myInts = { 5 , 10 , 15 };
bool [][] myBools = new bool [2][];
myBools [0] = new bool [2];
myBools [1] = new bool [1];
double [ ,] myDoubles = new double [2 , 2];
string [] myStrings = new string [3];
Console . WriteLine (" myInts [0]: {0} , myInts [1]: {1} , myInts [2]: {2}" , myInts [0] , myInts [1] , myInts
myBools [0][0] = true ;
myBools [0][1] = false ;
myBools [1][0] = true ;
Console . WriteLine (" myBools [0][0]: {0} , myBools [1][0]: {1}" , myBools [0][0] , myBools [1][0]);
myDoubles [0 , 0] = 3.147;
myDoubles [0 , 1] = 7.157;
23
17
18
19
20
21
22
23
24
25
myDoubles [1 , 1] = 2.117;
myDoubles [1 , 0] = 56.00138917;
Console . WriteLine (" myDoubles [0 , 0]: {0} , myDoubles [1 , 0]: {1}" , myDoubles [0 , 0] , myDoubles [1 , 0]
myStrings [0] = " Joe ";
myStrings [1] = " Matt ";
myStrings [2] = " Robert ";
Console . WriteLine (" myStrings [0]: {0} , myStrings [1]: {1} , myStrings [2]: {2}" , myStrings [0] , myStr
}
}
You can make jagged arrays or multi-dimensional arrays. Jagged is basically array of arrays. Array size is any
integer type value. It uses a zero-based index.
Control statements like if and else work much like C++.
1
2
3
4
5
6
7
8
9
10
11
Switch statement can work for booleans, enums, integral types, and strings. You break the switch statement with
one of the following branching statements:
using System ;
class WhileLoop
{
public static void Main ()
{
int myInt = 0;
while ( myInt < 10)
{
Console . Write ("{0} " , myInt );
myInt ++;
}
Console . WriteLine ();
}
}
24
CHAPTER 5. LECTURE 5
Another example with a for loop.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System ;
class ForLoop
{
public static void Main ()
{
for ( int i =0; i < 20; i ++)
{
if ( i == 10)
break ;
if ( i % 2 == 0)
continue ;
Console . Write ("{0} " , i );
}
Console . WriteLine ();
}
}
using System ;
class ForEachLoop
{
public static void Main ()
{
string [] names = {" Cheryl " , " Joe " , " Matt " , " Robert "};
foreach ( string person in names )
{
Console . WriteLine ("{0} " , person );
}
}
}
using System ;
class OneMethod
{
public static void Main ()
{
string myChoice ;
OneMethod om = new OneMethod ();
myChoice = om . getChoice ();
}
string getChoice ()
25
15
16
17
18
{
return
example
}
}
The this pointer in methods refers to the object on which the method is called. Parameters can be ref parameter
which are passed by reference, out parameters which are used for return values or the params argument for variable
arguments. Here is an example of the last:
1
2
3
4
5
6
// show a d d r e s s e s
void viewAddresses ( params string [] names )
{
foreach ( string name in names )
{
Console . WriteLine (" Name : {0}" , name );
}
26
CHAPTER 5. LECTURE 5
Chapter 6
Lecture 6
Namespaces allow name reuse. For example, a Console class can reside in multiple libraries. Here is an example of
namespace declaration:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Namespace D e c l a r a t i o n
using System ;
// The C \# Station N a m e s p a c e
namespace csharp_station
{
// Program start class
class NamespaceCSS {
// Main begins program execution .
public static void Main ()
{
// Write to c o n s o l e
Console . WriteLine (" This is the new C \# Station Namespace .");
}
}
}
// Namespace D e c l a r a t i o n
using System ;
// helper c l a s s
class OutputClass
{
string myString ;
// C o n s t r u c t o r
public OutputClass ( string inputString )
myString = inputString ;
}
// Instance M e t h o d
27
28
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
CHAPTER 6. LECTURE 6
public void printString ()
{
Console . WriteLine ("{0}" , myString );
}
// D e s t r u c t o r
~ OutputClass ()
{
// Some resource cleanup r o u t i n e s
}
}
// Program start c l a s s
class ExampleClass
{
// Main begins program execution .
public static void Main ()
{
// Instance of O u t p u t C l a s s
OutputClass outCl = new
OutputClass (" This is printed by the output class .");
// Call Output class m e t h o d
outCl . printString ();
}
}
Multiple classes are conventionally stored in multiple files. To create a new class in IDE, use the new class wizard.
Multiple .cs files can be compiled as csc a.cs b.cs c.cs. Default ctors are written with no arguments when no ctor is
written. An initializer list can be used to use an alternate constructor.
public OutputClass() : this("Default Constructor String") { }
Multiple ctors can be written. Types of class members in C# are instance and static. For every new occurrence
there are new instance vars.
OutputClass oc1 = new OutputClass("OutputClass1");
OutputClass oc2 = new OutputClass("OutputClass2");
Now oc1.printstring or oc2.printstring will access dierent instance variables. On the other hand static members
have only one copy.
public static void staticPrinter()
{
Console.WriteLine("There is only one of me.");
}
Then you could call that function from Main() like this:
OutputClass.staticPrinter();
Static ctor exists to initialize class static members. Its called only once. It has no parameters. Destructors (dtors)
are called by garbage collector. public methods accessed outside class. public classes accessed outside assembly.
A class can contain Constructors, Destructors, Fields, Methods, Properties, Indexers, Delegates, Events, and Nested
Classes.
Inheritance introduces the concept of base classes and derived classes. Declaration of inheritance is done as Derived
: Base. Only single inheritance is supported. Multiple interface inheritance discussed later.
1
2
3
4
5
6
7
using System ;
p u b l i c class P a r e n t C l a s s {
public ParentClass ()
{
Console . WriteLine (" Parent Constructor .");
}
public void
print ()
{
Console . WriteLine (" I m a Parent Class .");
}
}
public
class ChildClass : P a r e n t C l a s s {
public ChildClass ()
{
Console . WriteLine (" Child Constructor .");
}
public static void
Main ()
{
ChildClass child = new ChildClass ();
child . print ();
}
}
29
Parent Constructor.
Child Constructor.
Im a Parent Class.
Derived class is exactly the same as base. Child class is a parent class except that derived is more special. Base
are automatically initialized before derived. How can derived communicate with the base i.e. the specialized part
communicate with the generic part. By using : base() at ctor time or base.x() later. new keyword used to
override methods. Cast back to base type to call an overridden method of base. Here is another example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Output is:
From Derived
Child Constructor.
Im a Parent Class.
Im a Child Class.
Im a Parent Class.
Polymorphism means to invoke derived class methods through base class reference during run-time. Normally (as
we saw) base class casting means base class method is called. Its handy when a group of objects is stored in array/list
and we invoke some method on all of them. They dont have to be the same type but if related by inheritance, they
can be cast.
1
2
3
4
5
6
7
8
9
10
using System ;
p u b l i c class D r a w i n g O b j e c t {
public virtual void
Draw ()
{
Console . WriteLine (" I m just a generic drawing
object .");
}
}
p u b l i c class Line : D r a w i n g O b j e c t {
public
override void Draw ()
{
Console . WriteLine (" I m a Line .");
}
}
p u b l i c class Circle : D r a w i n g O b j e c t {
public override void
Draw ()
{
Console . WriteLine (" I m a Circle .");
}
}
p u b l i c class
Square : D r a w i n g O b j e c t {
public override void Draw ()
{
Console . WriteLine (" I m a Square .");
}
}
using System ;
p u b l i c class D r a w D e m o {
public static int Main ( )
{
DrawingObject [] dObj = new DrawingObject [4];
dObj [0] = new Line ();
dObj [1] = new Circle ();
dObj [2] = new Square ();
dObj [3] = new DrawingObject (
foreach ( DrawingObject drawObj in dObj )
{
drawObj . Draw ();
}
return 0;
}
}
Polymorphic methods are declared with virtual keyword and the override keyword is used to provide an
implementation. Polymorphism needs the signatures to be the same. Because of inheritance, the three derived classes
can be treated as the base class. Because of polymorphism, the methods from drived can still be called. Output is:
30
CHAPTER 6. LECTURE 6
Im
Im
Im
Im
a Line.
a Circle.
a Square.
just a generic drawing object.
Properties allow protected reads and writes to a field of a class. Other languages require custom getters and
setters. C# allows accessing properties like fields. Properties allows changing representation, public fields dont. Other
languages use custom encapsulation to protect data.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using System ;
public class Customer
{
private int m_id = -1;
public int GetID ()
{
return m_id ;
}
public void SetID ( int id )
{
m_id = id ;
}
private string m_name = string . Empty ;
public string GetName ()
{
return m_name ;
}
public void SetName ( string name )
{
m_name = name ;
}
}
public class C u s t o m e r M a n a g e r W i t h A c c e s s o r M e t h o d s
{
public static void Main ()
{
Customer cust = new Customer ();
cust . SetID (1);
cust . SetName (" Amelio Rosales ");
Console . WriteLine (
" ID : {0} , Name : {1}" ,
cust . GetID () ,
cust . GetName ());
Console . ReadKey ();
}
}
Its such a common pattern that C# has a dedicated language feature for it.
1
2
using System ;
public class Customer
31
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
{
private int m_id = -1;
public int ID
{
get
{
return m_id ;
}
set
{
m_id = value ;
}
}
private string m_name = string . Empty ;
public string Name
{
get
{
return m_name ;
}
set
{
m_name = value ;
}
}
}
public class C u s t o m e r M a n a g e r W i t h P r o p e r t i e s
{
public static void Main ()
{
Customer cust = new Customer ();
cust . ID = 1;
cust . Name = " Amelio Rosales ";
Console . WriteLine (
" ID : {0} , Name : {1}" ,
cust . ID ,
cust . Name );
Console . ReadKey ();
}
}
Getters return, setters use value. Next we discuss read-only peroperties. Here is an example that uses read-only
properties.
1
2
3
4
5
6
7
8
9
using System ;
public class Customer
{
private int m_id = -1;
private string m_name = string . Empty ;
public Customer ( int id , string name )
{
32
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
CHAPTER 6. LECTURE 6
m_id = id ;
m_name = name ;
}
public int ID
{
get
{
return m_id ;
}
}
public string Name
{
get
{
return m_name ;
}
}
}
public class R e a d O n l y C u s t o m e r M a n a g e r
{
public static void Main ()
{
Customer cust = new Customer (1 , " Amelio Rosales ");
Console . WriteLine (
" ID : {0} , Name : {1}" ,
cust . ID ,
cust . Name );
Console . ReadKey ();
}
}
This example has only get and no implementation of set. So what about write-only properties. Yes, they exist and
have an implementation of set but not get.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System ;
public class Customer
{
private int m_id = -1;
public int ID
{
set
{
m_id = value ;
}
}
private string m_name = string . Empty ;
public string Name
{
set
{
m_name = value ;
33
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
}
}
public void Di s p la y C us t o me r D at a ()
{
Console . WriteLine (" ID : {0} , Name :
{1}" , m_id , m_name );
}
}
public class W r i t e O n l y C u s t o m e r M a n a g e r
{
public static void Main ()
{
Customer cust = new Customer ();
cust . ID = 1;
cust . Name = " Amelio Rosales ";
cust . Di s p la y C us t o me r D at a ();
Console . ReadKey ();
}
}
34
CHAPTER 6. LECTURE 6
Chapter 7
Lecture 7
Auto-implemented properties improve the common-case we saw. Here is the same example using auot-implemented
properties. Properties have the same idea as getters and setters. They just allow simplified syntax. Same idea of
backing store and a simplified syntax for the general case is enabled by auto-implemented properties.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System ;
public class Customer
{
public int ID { get ; set ; }
public string Name { get ; set ; }
}
public class A u t o I m p l e m e n t e d C u s t o m e r M a n a g e r
{
static void Main ()
{
Customer cust = new Customer ();
cust . ID = 1;
cust . Name = " Amelio Rosales ";
Console . WriteLine (
" ID : {0} , Name : {1}" ,
cust . ID ,
cust . Name );
Console . ReadKey ();
}
}
An indexer enables your class to be treated like an array. However you have your internal data representation
not an actual array. Its implemented using this keyword and square brackets syntax. It looks like a property
implementation. Here is an example.
1
2
3
4
5
6
7
8
9
10
class IntIndexer
{
private string [] myData ;
public IntIndexer ( int size )
{
myData = new string [ size ];
for ( int i =0; i < size ; i ++)
{
35
36
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
CHAPTER 7. LECTURE 7
myData [ i ] = " empty ";
}
}
public string this [ int pos ]
{
get
{
return myData [ pos ];
}
set
{
myData [ pos ] = value ;
}
}
static void Main ( string [] args )
{
int size = 10;
IntIndexer myInd = new IntIndexer ( size );
myInd [9] = " Some Value ";
myInd [3] = " Another Value ";
myInd [5] = " Any Value ";
Console . WriteLine ("\ nIndexer Output \ n ");
for ( int i =0; i < size ; i ++)
{
Console . WriteLine (" myInd [{0}]: {1}" , i , myInd [ i ]);
}
}
}
empty
empty
empty
Another Value
empty
Any Value
empty
empty
empty
Some Value
Indexers can take any number of parameters. The parameters can be integers, strings, or enums. Additionally they
can be overloaded with dierent type and number of parameters. The following example has overloaded indexers.
1
2
3
4
5
6
using System ;
/// < summary >
///
Implements overloaded indexers .
/// </ summary >
class OvrIndexer
37
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
{
private string [] myData ;
private int
arrSize ;
public OvrIndexer ( int size )
{
arrSize = size ;
myData = new string [ size ];
for ( int i =0; i < size ; i ++)
{
myData [ i ] = " empty ";
}
}
public string this [ int pos ]
{
get
{
return myData [ pos ];
}
set
{
myData [ pos ] = value ;
}
}
public string this [ string data ]
{
get
{
int count = 0;
for ( int i =0; i < arrSize ; i ++)
{
if ( myData [ i ] == data )
count ++;
}
return count . ToString ();
}
set
{
for ( int i =0; i < arrSize ; i ++)
{
if ( myData [ i ] == data )
myData [ i ] = value ;
}
}
}
static void Main ( string [] args )
{
int size = 10;
OvrIndexer myInd = new OvrIndexer ( size );
myInd [9] = " Some Value ";
myInd [3] = " Another Value ";
myInd [5] = " Any Value ";
myInd [" empty "] = " no value ";
38
66
67
68
69
70
71
72
73
74
75
76
CHAPTER 7. LECTURE 7
39
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using System ;
/// < summary >
/// Example of declaring and using
a struct
/// </ summary >
class StructExample
{
/// < summary >
/// Entry point : execution starts
here
/// </ summary >
static void Main ()
{
// instantiate a new Rectangle struct
// where Width is set to 1 and Height
is set to 3
Rectangle rect1 = new Rectangle ();
rect1 . Width = 1;
rect1 . Height = 3;
// show the value of Width and Height
for rect1
Console . WriteLine (" rect1 : {0}:{1}" , rect1 . Width , rect1 . Height );
Console . ReadKey ();
}
}
40
1
2
3
4
5
6
7
CHAPTER 7. LECTURE 7
// you can also use object
initialization syntax
Rectangle rect11 = new Rectangle
{
Width = 1 ,
Height = 3
};
Next we discuss Interfaces. They are declared like a class but have no implementation. There is only declarations
of events, indexers, methods and/or properties. They are inherited by classes which provide the real implementation.
So, what are interfaces good for if they dont implement functionality? They are great for putting together plug-nplay like architectures where components can be interchanged at will. The interface forces each component to expose
specific public members that will be used in a certain way.
Interfaces define a contract. For instance, if class foo implements the IDisposable interface, it is making a statement
that it guarantees it has the Dispose() method, which is the only member of the IDisposable interface. Any code that
wishes to use class foo may check to see if class foo implements IDisposable. When the answer is true, then the code
knows that it can call foo.Dispose()
To define an interface, we use the following syntax.
1
2
3
interface I M y I n t e r f a c e {
void MethodToI mpleme nt ();
}
The I prefix is a convention. There is no implementation, only semi-colon. There are only method signatures.
Lets now see how its used.
1
2
3
4
5
6
7
8
9
10
11
12
13
class In te rf a c e I m p l e m e n t e r : IMyInterface
{
static void Main ()
{
I n t e r f a c e I m p l e m e n t e r iImp = new InterfaceImplementer ();
iImp . Met hodToI mpleme nt ();
}
public void Me thodToI mpleme nt ()
{
Console . WriteLine (" MethodToImplement () called .");
}
}
The syntax used is same as for inheritance. Any signature dierence or not implementing some method in the
interface is an error. Interfaces can also be inherited. Here is an example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System ;
interface IParentInterface
{
void P a r e n t I n t e r f a c e M e t h o d ();
}
interface IMyInterface : IParentInterface
{
void Met hodToI mpleme nt ();
}
class In te rf a c e I m p l e m e n t e r : IMyInterface
{
static void Main ()
{
I n t e r f a c e I m p l e m e n t e r iImp = new InterfaceImplementer ();
41
19
20
21
22
23
24
25
26
27
28
29
30
31
32
42
CHAPTER 7. LECTURE 7
Chapter 8
Lecture 8
A delegate is a reference to a method. Its like function pointers in some other languages. Methods are algorithms
that operate on data. Sometimes the data needs a special operation e.g. a comparator in a sorting routine. We can
use a bad solution which would an if then else for all types we want our sorting routine to work for. There are two
good solutions. One is to implement a comparator interface in all types we want and then pass an instance of a type
that provides that interface. The other solution is using delegates i.e. references to functions. Now we can pass a
comparator delegate to the sorting algorithm.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System ;
// this is the delegate declaration
public delegate int Comparer ( object obj1 , object obj2 );
public class Name
{
public string FirstName = null ;
public string LastName = null ;
public Name ( string first , string last )
{
FirstName = first ;
LastName = last ;
}
// this is the delegate method handler
public static int Com pareFi rstNam es ( object name1 , object name2 )
{
string n1 = (( Name ) name1 ). FirstName ;
string n2 = (( Name ) name2 ). FirstName ;
if ( String . Compare ( n1 , n2 ) > 0)
{
return 1;
}
else if ( String . Compare ( n1 , n2 ) < 0)
{
return -1;
}
else
{
return 0;
}
}
43
44
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
CHAPTER 8. LECTURE 8
public override string ToString ()
{
return FirstName + " " + LastName ;
}
}
class SimpleDelegate
{
Name [] names = new Name [5];
public SimpleDelegate ()
{
names [0] = new Name (" Joe " , " Mayo ");
names [1] = new Name (" John " , " Hancock ");
names [2] = new Name (" Jane " , " Doe ");
names [3] = new Name (" John " , " Doe ");
names [4] = new Name (" Jack " , " Smith ");
}
static void Main ( string [] args )
{
SimpleDelegate sd = new SimpleDelegate ();
// this is the delegate instantiation
Comparer cmp = new Comparer ( Name . Compa reFirs tNames );
Console . WriteLine ("\ nBefore Sort : \ n ");
sd . PrintNames ();
// observe the delegate argument
sd . Sort ( cmp );
Console . WriteLine ("\ nAfter Sort : \ n ");
sd . PrintNames ();
}
// observe the delegate parameter
public void Sort ( Comparer compare )
{
object temp ;
for ( int i =0; i < names . Length ; i ++)
{
for ( int j = i ; j < names . Length ; j ++)
{
// using delegate " compare " just like
// a normal method
if ( compare ( names [ i ] , names [ j ]) > 0 )
{
temp = names [ i ];
names [ i ] = names [ j ];
names [ j ] = ( Name ) temp ;
}
}
}
}
public void PrintNames ()
{
Console . WriteLine (" Names : \ n ");
foreach ( Name name in names )
{
Console . WriteLine ( name . ToString ());
}
45
96
97
}
}
Next we discuss events. A C# event is a class member that is activated whenever the event it was designed for
occurs (fires). Anyone interested in the event can register and be notified as soon as the event fires. At the time an
event fires, methods registered with the event will be invoked.
Events and delegates work hand in hand. Any class, including the same class that the event is declared in, may
register one of its methods with the event. This occurs through a delegate, which specifies the signature of the method
that is registered for the event. The delegate may be one of the pre-defined .NET delegates or one that you declare
yourself. Then, you assign the delegate to the event, which eectively registers the method that will be called when
the event fires.
Here is an example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System ;
using System . Drawing ;
using System . Windows . Forms ;
// custom delegate
public delegate void Startdelegate ();
class Eventdemo : Form
{
// custom event
public event Startdelegate StartEvent ;
public Eventdemo ()
{
Button clickMe = new Button ();
clickMe . Parent = this ;
clickMe . Text = " Click Me ";
clickMe . Location = new Point (
( ClientSize . Width - clickMe . Width ) /2 ,
( ClientSize . Height - clickMe . Height )/2);
// an EventHandler delegate is assigned
// to the button s Click event
clickMe . Click += new EventHandler ( OnClickMeClicked );
// our custom " Startdelegate " delegate is assigned
// to our custom " StartEvent " event .
StartEvent += new Startdelegate ( OnStartEvent );
// fire our custom event
StartEvent ();
}
// this method is called when the " clickMe " button is pressed
public void OnClickMeClicked ( object sender , EventArgs ea )
{
MessageBox . Show (" You Clicked My Button !");
}
// this method is called when the " StartEvent " Event is fired
public void OnStartEvent ()
{
MessageBox . Show (" I Just Started !");
}
static void Main ( string [] args )
{
Application . Run ( new Eventdemo ());
}
}
To run this example in Visual Studio you will either have to add a reference to System.Drawing.dll and System.Windows.Forms.dll or you can make a new Windows Forms Project. This class inherits from Form, which essentially makes it a Windows Form. This automatically gives you all the functionality of a Windows Form, including Title
46
CHAPTER 8. LECTURE 8
Bar, Minimize/Maximize/Close buttons, System Menu, and Borders. It is started by calling the Run() method of the
static Application object with a reference to the form object as its parameter. The += syntax registers a delegate
with the event. Its fired like a method call. The Click event is pre-defined, EventHandler delegate is also already in
.NET. All you do is define your callback method (delegate handler method) that is invoked when someone presses the
clickMe button. The OnClickMeClicked() method, conforms to the signature of the EventHandler delegate.
Next, we discuss exception handling. There can be unforeseen errors in the program. There are some normal errors
and some exceptional errors e.g. file i/o error, system out of memory, null pointer exception. Exceptions are thrown.
They are derived from System.Exception class. They have a message property, contain a stackTrace, a toString method.
Identifying the exceptions youll need to handle depends on the routine youre writing e.g. System.IO.File.OpenRead()
could throw SecurityException, ArgumentException, ArgumentNullException, PathTooLongException, DirectoryNotFoundException, UnauthorizedAccessException, FileNotFoundException, or NotSupportedException.
Here is an example of exception handling:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System ;
using System . IO ;
class tryCatchDemo
{
static void Main ( string [] args )
{
try
{
File . OpenRead (" NonExistentFile ");
}
catch ( Exception ex )
{
Console . WriteLine ( ex . ToString ());
}
}
}
catch ( Fi le N o t F o u n d E x c e p t i o n fnfex )
{
Console . WriteLine ( fnfex . ToString ());
}
catch ( Exception ex )
{
Console . WriteLine ( ex . ToString ());
}
First handler that handles an exception catches it. Otherwise the exception bubbles up the caller stack until
someone handles it.
Chapter 9
Lecture 9
Exception can leave your program in an inconsistent state by not releasing resources or doing some other type of
cleanup. Sometimes you need to perform clean up actions whether or not your program succeeds. These are good
candidates for using a finally block e.g. a filestream must be closed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System ;
using System . IO ;
class FinallyDemo
{
static void Main ( string [] args )
{
FileStream outStream = null ;
FileStream inStream = null ;
try
{
outStream = File . OpenWrite (" DestinationFile . txt ");
inStream = File . OpenRead (" BogusInputFile . txt ");
}
catch ( Exception ex )
{
Console . WriteLine ( ex . ToString ());
}
finally
{
if ( outStream != null )
{
outStream . Close ();
Console . WriteLine (" outStream closed .");
}
if ( inStream != null )
{
inStream . Close ();
Console . WriteLine (" inStream closed .");
}
}
}
}
The alternate would be to duplicate code after catch and in catch. But finally is a neat cleanup solution.
Next, we discuss attributes. Attributes add declarative information to your programs. They are used for various
purposes during runtime. They can be used at design time by application development tools. For example, DllImportAttribute allows a program to communicate with Win32 libraries. ObsoleteAttribute causes a compile-time warning
to appear. Such things would be difficult to accomplish with normal code. Attributes add metadata to your programs.
47
48
CHAPTER 9. LECTURE 9
When your C# program is compiled, it creates a file called an assembly, which is normally an executable or DLL
library. Assemblies are self-describing because they have metadata. Via reflection, a programs attributes can be
retrieved from its assembly metadata. Attributes are classes that can be written in C# and are used to decorate your
code with declarative information. Its a powerful concept. It lets you extend your language by creating customized
declarative syntax with attributes.
Attributes are generally applied physically in front of type and type member declarations. They are declared with
square brackets, [ and ] surrounding the attribute such as [ObsoleteAttribute]. The Attribute part of the
attribute name is optional i.e. [Obsolete] is correct as well. Parameter lists are also possible.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System ;
class Basi cA tt ri bu te Dem o
{
[ Obsolete ]
public void M y F i r s t d e p r e c a t e d M e t h o d ()
{
Console . WriteLine (" Called My F ir st d ep r ec at e dM e th od ().");
}
[ ObsoleteAttribute ]
public void M y S e c o n d D e p r e c a t ed M e t h o d ()
{
Console . WriteLine (" Called M yS e c o nd D e p re c a t ed M e t ho d ().");
}
[ Obsolete (" You shouldn t use this method anymore .")]
public void M y T h i r d D e p r e c a t e d M e t h o d ()
{
Console . WriteLine (" Called My T hi rd D ep r ec at e dM e th od ().");
}
// make the program thread safe for COM
[ STAThread ]
static void Main ( string [] args )
{
B asi cA tt ri bu te De mo attrDemo = new BasicAttributeDemo ();
attrDemo . M y Fi rs t de p re ca t e d M e t h o d ();
attrDemo . M y S e co n d D ep r e c at e d M e t h o d ();
attrDemo . M y Th ir d De p re ca t e d M e t h o d ();
}
}
49
both positional and named parameters [DllImport(User32.dll, EntryPoint=MessageBox)]. Positional parameters come before named parameters. There is no order requirement on named parameters.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System ;
[ assembly : CLSCompliant ( true )]
public class At t r ib u t eT a r ge t d em o
{
public void N o n C l s C o m p l i a n t M et h o d ( uint nclsParam )
{
Console . WriteLine (" Called N onCls Comp liant Meth od ().");
}
[ STAThread ]
static void Main ( string [] args )
{
uint myUint = 0;
A tt r i bu t e Ta r g et d e mo tgtdemo = new AttributeTargetdemo ();
tgtdemo . N onCls Comp lian tMeth od ( myUint );
}
}
using System ;
// declares the enum
public enum Volume
{
Low , _
Medium ,
High
}
// demonstrates how to use the enum
class EnumSwitch
{
static void Main ()
{
// create and initialize
// instance of enum type
Volume myVolume = Volume . Medium ;
// make decision based
// on enum value
switch ( myVolume )
{
case Volume . Low :
Console . WriteLine (" The volume has been turned Down .");
break ;
case Volume . Medium :
Console . WriteLine (" The volume is in the middle .");
break ;
case Volume . High :
Console . WriteLine (" The volume has been turned up .");
break ;
}
Console . ReadLine ();
}
50
33
CHAPTER 9. LECTURE 9
}
Default underlying type of an enum is int. It can be changed by specifying a base. Valid base types include
byte, sbyte, short, ushort, int, uint, long, and ulong. Default value of first member is 0. You can assign any member
a ny value. If it is unassigned it gets +1 the value of its predecessor.
1
2
3
4
5
6
To enumerate values.
1
2
3
4
5
6
7
Next topic is operator overloading. You can add operators to your own types e.g. a matrix type can have an add
and a dot product operator etc.
1
2
3
4
5
6
Matrix
Matrix
Matrix
Matrix
Matrix
Matrix
result
result
result
result
result
result
=
=
=
=
=
=
It should not be used when its not natural to be used. Its implementation syntax is:
1
2
3
4
Here is an example.
1
2
3
4
using System ;
class Matrix
{
51
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Overloaded operators must be static. They must be declared in the class for which the operator is defined. It is
required that matching operators are both defined, e.g. == and != so that the behavior is consistent.
Access modifiers on types and assemblies provide encapsulation. They are: private, protected, internal, protected
internal, and public.
Next, we see how generic collections are used: There is a very useful List collection. It is better than ArrayList of
objects in earlier .NET versions. Another useful collection is DictionaryTKey,TValue vs. a non-generic HashTable
of objects. We write using System.Collections.Generic to include these collections.
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
List < int > myInts = new List < int >();
myInts . Add (1);
myInts . Add (2);
myInts . Add (3);
52
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
CHAPTER 9. LECTURE 9
}
Dictionary < int , Customer > customers = new Dictionary < int , Customer >();
Customer cust1 = new Customer (1 , " Cust 1");
Customer cust2 = new Customer (2 , " Cust 2");
Customer cust3 = new Customer (3 , " Cust 3");
customers . Add ( cust1 . ID , cust1 );
customers . Add ( cust2 . ID , cust2 );
customers . Add ( cust3 . ID , cust3 );
foreach ( KeyValuePair < int , Customer > custKeyVal in customers )
{
Console . WriteLine (
" Customer ID : {0} , Name : {1}" ,
custKeyVal . Key ,
custKeyVal . Value . Name );
}
Chapter 10
Lecture 10
Lets discuss Anonymous methods. It is used with delegates and handlers and events. Anonymous methods result in
much less code. Anonymous method is a method without a name. You dont declare anonymous methods, Instead
they get hooked up directly to events. With delegates 1) you declare the delegate, 2) write a method with a signature
defined by the delegate interface, 3) declare the event based on that delegate, and 4) write code to hook the handler
method up to the delegate. To delcare an anonymous method, you just use keyword delegate followed by method
body.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
We can skip parameters when not using them. Here is an example with parameters.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System ;
using System . Windows . Forms ;
public partial class Form1 : Form
{
public Form1 ()
{
Button btnHello = new Button ();
btnHello . Text = " Hello ";
btnHello . Click +=
delegate
{
MessageBox . Show (" Hello ");
};
Button btnGoodBye = new Button ();
btnGoodBye . Text = " Goodbye ";
53
54
19
20
21
22
23
24
25
26
27
28
29
30
We can create nullable value types by appending a question mark to a type name.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int ? unitsInStock = 5;
DateTime ? startDate ;
startDate = DateTime . Now ;
startDate = null ;
int availableUnits ;
if ( unitsInStock == null )
{
availableUnits = 0;
}
else
{
availableUnits = ( int ) unitsInStock ;
}
// OR just
int availableUnits = unitsInStock ?? 0;
We will now discuss debugging in Visual Studio. By printing output frequently we can debug. We can use
Console.Write to print. Breakpoints allow stopping the program during execution. Press F5 and execution will stop
at breakpoint. You can hover over variabeles for their current values. Locals, watch, call stack, immediate window
give you dierent information about the program. Your changes will have eect on the current execution. Conditional
breakpoints have a hit count and when hit condition.
We now discuss XML. XML or eXtensible Markup Language is widely used for exchanging data. Its readable for
both humans and machines. Its a stricter version of HTML. Its made of tags, attributes, and values.
1
2
3
4
< gesmes : Envelope xmlns : gesmes =" http :// www . gesmes . org / xml /2002 -08 -01" xmlns =" http :// www . ecb . int / v
< gesmes : subject > Reference rates </ gesmes : subject >
< gesmes : Sender >
< gesmes : name > European Central Bank </ gesmes : name >
</ gesmes : Sender >
< Cube >
< Cube time ="2012 -12 -18" >
< Cube currency =" USD " rate ="1.3178"/ >
< Cube currency =" JPY " rate ="110.53"/ >
< Cube currency =" BGN " rate ="1.9558"/ >
< Cube currency =" CZK " rate ="25.200"/ >
< Cube currency =" DKK " rate ="7.4603"/ >
< Cube currency =" GBP " rate ="0.81280"/ >
< Cube currency =" HUF " rate ="288.40"/ >
55
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
We will now learn to read XML with the XmlReader class. There are two methods to read XML document. Using
XmlDocument and XmlReader. XmlDocuments reads entire document in memory, lets you go forward, backward,
even apply XPath searches on it. XmlReader is fast, uses less memory and provides one element at a time.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System ;
using System . Text ;
using System . Xml ;
namespace ParsingXml
{
class Program
{
static void Main ( string [] args )
{
XmlReader xmlReader = XmlReader . Create (" http :// www . ecb . int / stats / eurofxref / eurofxref
while ( xmlReader . Read ())
{
if (( xmlReader . NodeType == XmlNodeType . Element ) && ( xmlReader . Name == " Cube "))
{
if ( xmlReader . HasAttributes )
Console . WriteLine ( xmlReader . GetAttribute (" currency ") + ": " + xmlReader .
}
}
Console . ReadKey ();
}
}
}
Using XmlDocument is easier. No order is required. DocumentElement is the root element and ChildNodes is the
set of children of any node.
56
1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace ParsingXml
{
class Program
{
static void Main ( string [] args )
{
XmlDocument xmlDoc = new XmlDocument ();
xmlDoc . Load (" http :// www . ecb . int / stats / eurofxref / eurofxref - daily . xml ");
foreach ( XmlNode xmlNode in xmlDoc . DocumentElement . ChildNodes [2]. ChildNodes [0]. Child
Console . WriteLine ( xmlNode . Attributes [" currency "]. Value + ": " + xmlNode . Attribut
Console . ReadKey ();
}
}
}
An XmlNode is derived from XmlElement and contains Name, InnerText, InnerXml, OuterXml, and Attributes.
XPath is a cross-platform Xml Query language. We will look at basic examples only. We will see XmlDocument
methods that take XPath queries and return XmlNode(s) in particular SelectSingleNode and SelectNodes. We will
use the RSS feed from CNN, located at http://rss.cnn.com/rss/edition world.rss. It has a hierarchy of rss containing
channel containing item.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System ;
using System . Text ;
using System . Xml ;
namespace ParsingXml
{
class Program
{
static void Main ( string [] args )
{
XmlDocument xmlDoc = new XmlDocument ();
xmlDoc . Load (" http :// rss . cnn . com / rss / edition_world . rss ");
XmlNode titleNode = xmlDoc . SelectSingleNode ("// rss / channel / title ");
if ( titleNode != null )
Console . WriteLine ( titleNode . InnerText );
Console . ReadKey ();
}
}
}
using System ;
using System . Text ;
using System . Xml ;
namespace ParsingXml
{
class Program
{
static void Main ( string [] args )
{
XmlDocument xmlDoc = new XmlDocument ();
xmlDoc . Load (" http :// rss . cnn . com / rss / edition_world . rss ");
XmlNodeList itemNodes = xmlDoc . SelectNodes ("// rss / channel / item ");
foreach ( XmlNode itemNode in itemNodes )
{
XmlNode titleNode = itemNode . SelectSingleNode (" title ");
XmlNode dateNode = itemNode . SelectSingleNode (" pubDate ");
57
18
19
20
21
22
23
24
using System ;
using System . Text ;
using System . Xml ;
namespace ParsingXml
{
class Program
{
static void Main ( string [] args )
{
XmlDocument xmlDoc = new XmlDocument ();
xmlDoc . Load (" http :// rss . cnn . com / rss / edition_world . rss ");
XmlNodeList itemNodes = xmlDoc . SelectNodes ("// rss / channel / item ");
foreach ( XmlNode itemNode in itemNodes )
{
XmlNode titleNode = itemNode . SelectSingleNode (" title ");
XmlNode dateNode = itemNode . SelectSingleNode (" pubDate ");
if (( titleNode != null ) && ( dateNode != null ))
Console . WriteLine ( dateNode . InnerText + ": " + titleNode . InnerText );
}
Console . ReadKey ();
}
}
}
using System ;
using System . Text ;
using System . Xml ;
namespace WritingXml
{
class Program
{
static void Main ( string [] args )
{
XmlWriter xmlWriter = XmlWriter . Create (" test . xml ");
xmlWriter . Wr it eS ta rt Document ();
xmlWriter . WriteS tartElement (" users ");
xmlWriter . WriteS tartElement (" user ");
xmlWriter . W r i t e A t t r i buteString (" age " , "42");
xmlWriter . WriteString (" John Doe ");
xmlWriter . WriteEndElement ();
xmlWriter . WriteS tartElement (" user ");
xmlWriter . W r i t e A t t r i buteString (" age " , "39");
xmlWriter . WriteString (" Jane Doe ");
58
25
26
27
28
29
using
using
using
using
System ;
System . Text ;
System . Xml ;
System . Xml . Serialization ;
namespace WritingXml
{
class Program
{
static void Main ( string [] args )
{
XmlDocument xmlDoc = new XmlDocument ();
XmlNode rootNode = xmlDoc . CreateElement (" users ");
xmlDoc . AppendChild ( rootNode );
XmlNode userNode = xmlDoc . CreateElement (" user ");
XmlAttribute attribute = xmlDoc . CreateAttribute (" age ");
attribute . Value = "42";
userNode . Attributes . Append ( attribute );
userNode . InnerText = " John Doe ";
rootNode . AppendChild ( userNode );
userNode = xmlDoc . CreateElement (" user ");
attribute = xmlDoc . CreateAttribute (" age ");
attribute . Value = "39";
userNode . Attributes . Append ( attribute );
userNode . InnerText = " Jane Doe ";
rootNode . AppendChild ( userNode );
xmlDoc . Save (" test - doc . xml ");
}
}
}
using
using
using
using
System ;
System . Text ;
System . Xml ;
System . Xml . Serialization ;
namespace WritingXml
{
class Program
{
static void Main ( string [] args )
{
59
12
13
14
15
16
17
18
19
20
21
22
23
60
Chapter 11
Lecture 11
Lets start discussing extension methods.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System ;
using System . IO ;
namespace F i l e H a n d l i n g A r t i c l e A p p
{
class Program
{
static void Main ( string [] args )
{
61
62
10
11
12
13
14
15
16
17
18
19
20
21
using System ;
using System . IO ;
namespace F i l e H a n d l i n g A r t i c l e A p p
{
class Program
{
static void Main ( string [] args )
{
if ( File . Exists (" test . txt "))
{
string content = File . ReadAllText (" test . txt ");
Console . WriteLine (" Current content of file :");
Console . WriteLine ( content );
}
Console . WriteLine (" Please enter new content for the file - type exit and press enter
string newContent = Console . ReadLine ();
while ( newContent != " exit ")
{
File . AppendAllText (" test . txt " , newContent + Environment . NewLine );
newContent = Console . ReadLine ();
}
}
}
}
If using keyword is not used, manually call the Close method of the stream.
1
2
3
4
5
6
7
8
9
10
Console . WriteLine (" Please enter new content for the file - type exit and press enter to finish e
using ( StreamWriter sw = new StreamWriter (" test . txt "))
{
string newContent = Console . ReadLine ();
while ( newContent != " exit ")
{
sw . Write ( newContent + Environment . NewLine );
newContent = Console . ReadLine ();
}
}
Console . WriteLine (" Please enter new content for the file - type exit and press enter to finish e
using ( StreamWriter sw = new StreamWriter (" test . txt "))
{
string newContent = Console . ReadLine ();
while ( newContent != " exit ")
{
63
7
8
9
10
Console . WriteLine (" Please enter new content for the file - type exit and press enter to finish e
using ( StreamWriter sw = new StreamWriter (" test . txt "))
{
string newContent = Console . ReadLine ();
while ( newContent != " exit ")
{
sw . Write ( newContent + Environment . NewLine );
newContent = Console . ReadLine ();
}
}
Console . WriteLine (" Please enter a name for the new directory :");
string newDirName = Console . ReadLine ();
if ( newDirName != String . Empty )
{
Directory . CreateDirectory ( newDirName );
if ( Directory . Exists ( newDirName ))
{
Console . WriteLine (" The directory was created !");
64
9
10
11
using
using
using
using
System ;
System . Collections . Generic ;
System . Text ;
System . Reflection ;
namespace ReflectionTest
{
class Program
{
static void Main ( string [] args )
{
string test = " test ";
Console . WriteLine ( test . GetType (). FullName );
Console . WriteLine ( typeof ( Int32 ). FullName );
Console . ReadKey ();
}
}
}
65
Here is another example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using
using
using
using
System ;
System . Collections . Generic ;
System . Text ;
System . Reflection ;
namespace ReflectionTest
{
class Program
{
static void Main ( string [] args )
{
Assembly assembly = Assembly . G e t E x e c u t i n g A s s e m b l y ();
Type [] assemblyTypes = assembly . GetTypes ();
foreach ( Type t in assemblyTypes )
Console . WriteLine ( t . Name );
Console . ReadKey ();
}
}
class DummyClass
{
// Just here to make the output a tad less boring :)
}
}
using
using
using
using
System ;
System . Collections . Generic ;
System . Text ;
System . Reflection ;
namespace ReflectionTest
{
class Program
{
static void Main ( string [] args )
{
Type testType = typeof ( TestClass );
ConstructorInfo ctor = testType . GetConstructor ( System . Type . EmptyTypes );
if ( ctor != null )
{
object instance = ctor . Invoke ( null );
MethodInfo methodInfo = testType . GetMethod (" TestMethod ");
Console . WriteLine ( methodInfo . Invoke ( instance , new object [] { 10 }));
}
Console . ReadKey ();
}
}
public class TestClass
{
private int testValue = 42;
public int TestMethod ( int numberToAdd )
{
return this . testValue + numberToAdd ;
}
66
32
33
using
using
using
using
System ;
System . Collections . Generic ;
System . Text ;
System . Reflection ;
namespace ReflectionTest
{
class Program
{
private static int a = 5 , b = 10 , c = 20;
We will now build a complete profile save load system with reflection.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System ;
using System . IO ;
using System . Reflection ;
class Program
{
public class Person
{
public void Load ()
{
if ( File . Exists (" settings . dat "))
{
Type type = this . GetType ();
string propertyName , value ;
string [] temp ;
char [] splitChars = new char [] { | };
PropertyInfo propertyInfo ;
67
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
68
80
81
82
83
84
85
86
87
Chapter 12
Lecture 12
We will start discussing WPF (Windows Presentation Foundations) now. It was publicly announced in 2003 (codenamed Avalon). WPF 4 was released in April 2010. It has a steep learning curve. Code has to be written in many
places. There are multiple ways to do a particular task.
WPF enables polished user interfaces which are getting a lot of attention. It enables rapid iterations and major
interface changes throughout the development process. It allows to keep user interface description and implementation
separate. Developers can create an ugly application which designers can re-theme. Win32 style of programming
makes such re-theming difficult. The code to re-paint the user interface is mixed up with program logic. GDI was
an earlier user interface library introduced in windows 1.0 in 1985. OpenGL was a leap ahead introduced in the 90s
with DirectX coming in 95 and DirectX 2 in 96. GDI+ is a newer user interface library based on DirectX. It is also
used behind Xbox graphics. Next was Windows Forms which is the primary way of user interface design in C#. XNA
comes with managed library for DirectX and is great for game development (.net/com interoperability not required).
A simple example is drawing bitmaps on buttons which can be efficiently done using GDI.
The highlights of WPF are 1) broad integration (2D, 3D, video, speech libraries etc.) 2) Resolution Independence
with WPF giving emphasis on vector graphics 3) Hardware accelration as it is based on Direct3D but it can work using
software pipeline also if Direct3D hardware is not available. 4) Declrative progrmaming using eXtensible Application
Markup Language (XAML; pronounced Zammel). Custom attribute and configuration files were always there but
XAML is very rich. 5) Rich composition and customization e.g. you can create a ComboBox filled with animated
Buttons or a Menu filled with live video clips! And it is quite easy to skin applications.
In short, WPF aims to combine the best attributes of systems such as DirectX (3D and hardware acceleration),
Windows Forms (developer productivity), Adobe Flash (powerful animation support) and HTML (declarative markup).
The first release in November 2006 was WPF 3.0 because it shipped as part of the .NET Framework 3.0. WPF 3.5
came an year later. Next version as part of .NET 3.5 SP1 came in August 2008. WPF Toolkit released in Aug 2008
was experimental. The toolkit has quick releases. Regarding tool support, WPF extensions for Visual Studio 2005
came a few months after the first WPF release and a public release of expression blend. Now, Visual Studio 2012 is
a first class WPF devevelopment environment. Its mostly re-written using WPF and expression blend is 100% WPF
and is great for designing and prototyping WPF apps.
New things that came in WPF 3.5/3.5SP1 include Interactive3D with 2d elements in 3d scenes, first class interoperability with directX, Better data binding using XLINQ and better validation and debugging which reduces code,
Better special eects, High performance custom drawing, Text improvements, enhancements to Partial-trust apps,
improved deployment, and improved performance.
Things that came with WPF 4.0 include multi-touch support compatible with surface API v2, win7 support
like jump lists, new common dialogs etc., new controls like datagrid, calendar etc, easing animation functions (bounce,
elastic), enhanced styling with visual state manager, improved layout on pixel boundaries, non-blurry text but some
limitations so must opt-in, deployment improvements, and performance improvements.
Silverlight in comparison is a light-weight version for web. It chose to follow WPF appraoch. First released in 2007
and in April 2010 4th version was released near WPF 4. There is often confusion when to use one or the other. Both
can run in and outside the web. Silverlight is ostly a subset of WPF but there are some incompatibilities. Should I
use full .net or partial .net and should I have the ability to run on other devices e.g. macs. Ideally common codebase
should work for both but today best case is using #ifdefs to handle incompatibilities.
69
70
XAML is primarily used to describe interfaces in WPF and Silverlight. It is also used to express activities and
configurations in workflow foundation (WF) and windows communication foundation (WCF). Its a common language
for programmers and other experts e.g. UI design experts. Field specific development tools can be made. Field experts
are graphic designers. They can use a design tool such as expression blend. Other than co-ordinating with designers,
XAML is good for a concise way to represent UI or hierarchies of objects, encourages separation of front-end and
back-end, tool support with copy and paste, used by all WPF tools.
XAML is xml with a set of rules. Its a declrative programming language for creating and initializing objects. Its a
way to use .net apis. Comparisons with SVG, HTML etc are misguided. It has few keywords, not much elemetns. It
doesnt make sense without .net, like C# doesnt make sense without .net. Microsoft formalized XAML vocabluries,
e.g. WPF XAML vocabluary. Online specifications for XAML object specification language, and WPF and Silverlight
vocabluaries are available. XAML is used by other technologies as well although originally it was designed for WPF.
Also using XAML in WPF projects is optional. Everything can be done in procedural code as well (althought its rare
to find it done that way).
Chapter 13
Lecture 13
XAML specification defines rules that map .NET namespaces, types, properties, and events into XML namespaces,
elements, and attributes. Lets see XAML and equivalent C#.
1
< Button xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation " Content =" OK "/ >
System . Windows . Controls . Button b = new System . Windows . Controls . Button ();
b . Content = " OK ";
Declaring an XML element in XAML (known as an object element) is equivalent to instantiating the corresponding
.NET object via a default constructor. Setting an attribute on the object element is equivalent to setting a property
of the same name (called a property attribute) or hooking up an event handler of the same name (called an event
attribute).
System . Windows . Controls . Button b = new System . Windows . Controls . Button ();
b . Click += new System . Windows . Rout ed Ev en tH and le r ( button_Click );
b . Content = " OK ";
XAML can no longer run standalone in the browser becuase of the butto click method event handlers are
attached before properties are set.
Lets discuss namespaces. Mapping to the namespace used above and other WPF namespaces is hard-coded inside the WPF assemblies. Its just an arbitrary string like any namespace. The root object element in XAML
must specify at least one XML namespace that is used to qualify itself and any child elements. Additional XML
namespaces (on the root or on children) must be given a distinct prefix to be used on any identifiers from that
namespace. e.g, typically a second namespace with the prefix x (denoted by using xmlns:x instead of just xmlns):
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
This is the XAML language namespace, which maps to types in the System.Windows.Markup namespace but also
defines some special directives for the XAML compiler or parser.
All of the following are mapped with http://schemas.microsoft.com/winfx/2006/xaml/presentation.
1
2
3
4
5
6
7
8
9
10
System . Windows
System . Windows . Automation
System . Windows . Controls
System . Windows . Controls . Primitives . System . Windows . Data
System . Windows . Documents
System . Windows . Forms . Integration
System . Windows . Ink
System . Windows . Input
System . Windows . Media
System . Windows . Media . Animation
71
72
11
12
13
14
15
16
System . Windows . Controls . Button b = new System . Windows . Controls . Button ();
System . Windows . Shapes . Rectangle r = new System . Windows . Shapes . Rectangle ();
r . Width = 40;
r . Height = 40;
r . Fill = System . Windows . Media . Brushes . Black ;
b . Content = r ; // Make the square the content of the Button
and in XAML
1
2
3
4
5
< Button xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation " >
< Button . Content >
< Rectangle Height ="40" Width ="40" Fill =" Black "/ >
</ Button . Content >
</ Button >
The period distinguishes property elements from object elements. It doesnt have attributes except x:uid for
localization. The syntax can be used for simple properties as well. The following two are equivalent.
1
2
3
4
5
6
7
8
9
10
< Button xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation " Content =" OK " Backgroun
< Button xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation " >
< Button . Content >
OK
</ Button . Content >
< Button . Background >
White
</ Button . Background >
</ Button >
System . Windows . Controls . Button b = new System . Windows . Controls . Button ();
b . Content = " OK ";
b . Background = System . Windows . Media . Brushes . White ;
WPF provides type converters for many common data types: Brush, Color, FontWeight, Point, and so on. Classes
deriving from TypeConverter (BrushConverter, ColorConverter, and so on) convert from string to the corresponding
types. You can also write your own type converters for custom data types.
1
2
3
4
5
< Button xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation " Content =" OK " >
< Button . Background >
< SolidColorBrush Color =" White "/ >
</ Button . Background >
</ Button >
< Button xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation " Content =" OK " >
< Button . Background >
< SolidColorBrush >
< SolidColorBrush . Color >
< Color A ="255" R ="255" G ="255" B ="255"/ >
</ SolidColorBrush . Color >
</ SolidColorBrush >
</ Button . Background >
</ Button >
73
Even that requires a type converter for Byte.
1
2
3
System . Windows . Controls . Button b = new System . Windows . Controls . Button ();
b . Content = " OK ";
b . Background = ( Brush ) System . ComponentModel . TypeDescriptor . GetConverter ( typeof ( Brush )). C o n v e r t F r
Constants in strings cause problems with run time exception not caught at compile time. Althought for xaml
Visual Studio will check it at compile time. Lets see how to find the type converter for a type.
Lets discuss markup extensions now. Markup extensions, like type converters, enable you to extend the expressiveness of XAML. Both can evaluate a string attribute value at runtime (except for a few built-in markup extensions
for performance reasons) and produce an appropriate object based on the string. As with type converters, WPF ships
with several markup extensions built in.
Unlike type converters, however, markup extensions are invoked from XAML with explicit and consistent syntax.
For this reason, using markup extensions is a preferred approach for extending XAML. For example, if you want to set
a controls background to a fancy gradient brush with a simple string value, you can write a custom markup extension
that supports it even though the built-in BrushConverter does not. Whenever an attribute value is enclosed in curly
braces ({}), the XAML compiler/parser treats it as a markup extension value rather than a literal string (or something
that needs to be type-converted). Here are few examples:
1
2
3
4
< Button xmlns = http :// schemas . microsoft . com / winfx /2006/ xaml / presentation Content = {}{ This is
< Button xmlns = http :// schemas . microsoft . com / winfx /2006/ xaml / presentation > < Button . Content >
{ This is not a markup extension !}
</ Button . Content > </ Button >
Because markup extensions are just classes with default constructors, they can be used with property element
syntax.
1
2
3
4
5
< Button xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml "
Background = "{ x : Null }"
Height = "{ x : Static SystemParameters . IconHeight }"
Content = "{ Binding Path = Height , RelativeSource ={ RelativeSource Mode = Self }}"/ >
It works because positional parameters have corresponding property value. Markup extension has the real code to
be executed.
An object element can have three types of children: a value for a content property, collection items, or a value that
can be type-converted to the object element. Designated property is the content property.
1
< Button xmlns = http :// schemas . microsoft . com / winfx /2006/ xaml / presentation Content = OK / >
< Button xmlns = http :// schemas . microsoft . com / winfx /2006/ xaml / presentation > OK
</ Button >
Also
1
2
< Button xmlns = h t t p :// schemas . microsoft . com / winfx /2006/ xaml / p r e s e n t a t i o n > < Button . Content >
< Rectangle Height =
4 0
Width =
4 0
Fill = B l a c k / > </ Button . Content >
</ Button >
h t t p :// schemas . microsoft . com / winfx /2006/ xaml / p r e s e n t a t i o n > < Rectangle Height
There is no requirement that the content property must actually be called Content; classes such as ComboBox,
ListBox, and TabControl (also in the System.Windows.Controls namespace) use their Items property as the content
property. Its designated with a custom attribute.
XAML enables you to add items to the two main types of collections that support indexing: lists and dictionaries.
1
2
3
< ListBox xmlns = h t t p :// schemas . microsoft . com / winfx /2006/ xaml / p r e s e n t a t i o n > < ListBox . Items >
< ListBoxItem Content = I t e m 1
/>
< ListBoxItem Content = I t e m 2
/ > </ ListBox . Items >
</ ListBox >
74
1
2
3
System . Windows . Controls . ListBox listbox = new System . Windows . Controls . ListBox (); System . Windows .
new System . Windows . Controls . ListBoxItem (); System . Windows . Controls . ListBoxItem item2 =
new System . Windows . Controls . ListBoxItem (); item1 . Content =
Item 1
; i t e m 2 . Content =
Ite
OR
1
2
h t t p :// schemas . microsoft . com / winfx /2006/ xaml / p r e s e n t a t i o n > < ListBoxItem Con
xmlns :
Chapter 14
Lecture 14
1
It works because a typeconverter exists that converts string to SolidColorBrush, although no designated content
property exists.
1
In fact, the above also works even although Brush is abstract. It works because of a type converter can convert a
string to a SolidColorBrush.
XAML works with classes designated with marked attributes. Usually these classes have default ctors and useful
properties. But what about other classes not designed for XAML. e.g. Hashtable.
1
2
3
Lets study XAML child element rules. If the type implements IList, call IList.Add for each child. Otherwise, if the
type implements IDictionary, call IDictionary.Add for each child, using the x:Key attribute value for the key and the
element for the value. (Although XAML2009 checks IDictionary before IList and supports other collection interfaces,
as described earlier.)
Otherwise, if the parent supports a content property (indicated by System.Windows.Markup.ContentPropertyAttribute)
and the type of the child is compatible with that property, treat the child as its value. Otherwise, if the child is plain
text and a type converter exists to transform the child into the parent type (and no properties are set on the parent
element), treat the child as the input to the type converter and use the output as the parent object instance. Otherwise,
treat it as unknown content and potentially raise an error
We can mix XAML and procedural code. Lets try this with XamlReader and XamlWriter.
1
2
3
4
5
6
75
76
1
2
< Button x : Name =" okButton " > OK </ Button >
Classes that already have a name property designate it as the special name using a custom attribute.
Lets see how to use named properties. Lets first use a Binding markup extension.
1
2
3
4
< StackPanel
xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation " >
< Label Target ="{ Binding ElementName = box }" Content =" Enter _text :"/ >
< TextBox Name =" box "/ > </ StackPanel >
It gives it focus when the Labels access key is pressed.) WPF 4 includes a new, simpler markup extension which
works at parse time.
1
2
3
4
5
< StackPanel
xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml " > < Label
Target ="{ x : Reference box }" Content =" Enter _text :"/ > < TextBox
Name =" box "/ > </ StackPanel >
< StackPanel
xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation " >
< Label Target =" box " Content =" Enter _text :"/ > < TextBox Name =" box "/ >
</ StackPanel >
Compiling xaml involves 3 steps converting a XAML file into a special binaryformat, embedding the converted
content asa binary resource in the assembly being built,and performing the plumbing that connects XAML with
procedural code automatically. C# and VB have best support in typical case, the first step is specifying a subclass
for the root element in a XAML file. Use the Class keyword for that.
1
2
3
4
1
2
3
4
5
6
7
8
9
10
11
12
13
< Window
xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml "
x : Class =" MyNamespace . MyWindow " > ... </ Window >
namespace MyNamespace
{
partial class MyWindow : Window
{
public MyWindow ()
{
// Necessary to call in order to load XAML - defined content !
I n it i a li z e Co m po n e nt ();
...
}
Any other members can go here ...
}
}
This is often refered as the code-behind file. We define event handlers here. The partial keyword is important.
When we add new items to certain WPF projects, Visual Studio does all this automatically for us.
Chapter 15
Lecture 15
BAML is binary application markup language. It just a compressed representation of XAML. There is even a BAML
reader available. Earlier there was CAML which stands for compiled application markup language but its not used
now.
Some glue code is generated when we use x:Class. Its kind of same as loading and parsing the XAML file. We
must call initializecomponent and we can refer named elements like class members.
Procedural code can even be written inside the XAML file.
1
2
3
4
5
6
7
8
9
10
11
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation " xmlns : x =" http :// schema
< Button Click =" button_Click " > OK </ Button >
<x : Code >
<![ CDATA [
void button_Click ( object sender , RoutedEventArgs e )
{
this . Close ();
}
]] >
</ x : Code >
</ Window >
We must avoid ]]. If we have to use them, we need < & etc. There is no good reason to embed code.
Internally its build into .cs file by build system. BAML can be converted back to XAML.
1
2
3
4
System . Uri uri = new System . Uri ("/ WpfApplication1 ; component / MyWindow . xaml " , System . UriKind . Relat
Window window = ( Window ) Application . LoadComponent ( uri );
string xaml = XamlWriter . Save ( window );
There are dierent loading mechanisms. We can load from resource, identified by original xaml file, or actually
integrated baml loaded.
Key features of XAML 2009 include full generics support using TypeArguments, dictionary keys of any type, builtin
system data types, creating objects with non-default ctors, getting instances via factory methods, event handlers can
be markup extensions returning delegates, define additional members and properties.
System.Xaml.XamlXmlReader etc. can be extended with readers and writers for a lot of formats. It abstracts
dierences in Xaml formats like accessing a content property, property element, or a property attribute.
77
78
XAML 2006 keywords include x:AsyncRecords Controls the size of asynchronous XAML-loading chunks, x:Class,
x:ClassModifier visibility, public by default, x:Code, x:ConnectionId not for public use, x:FieldModifier field
visibility (internal def), x:Key, x:Name, x:Shared =false means same resource instance not shared, x:SubClass only
needed when partial not supported, x:Synchronous mode xaml loaded in async mode, x:TypeArguments used only
with root with x:Class in xaml2006, x:Uid represents system.uri, and x:XData data opaque for xaml parser.
Markup extensions often confused as keywords are x:Array use with x:Type to define type of array, x:Null,
x:Reference to named element, x:Static static property field, and x:Type just like typeof operator.
In summary, we can convert xaml into C#, often apis are optimized for xaml and can look clunky in C#, wpf
applications have deep hierarchy, small building blocks. Two complaints are that xml too verbose to type and slow to
parse (tools and baml fix it partially).
Lets discuss wpf fundamentals now. WPF concepts are above and beyond .net concepts. Its the cause of the steep
learning curve of wpf. It has a deep inheritance hierarchy. There are a handful of fundamental classes.
Object is the base class for all .NET classes and the only class in the figure that isnt WPF specific.
DispatcherObject is the base class meant for any object that wishes to be accessed only on the thread that created
it. Most WPF classes derive from DispatcherObject and are therefore inherently thread-unsafe. The Dispatcher part
of the name refers to WPFs version of a Win32-like message loop, discussed further in Chapter 7, Structuring and
Deploying an Application of the book.
79
DependencyObject is the base class for any object that can support dependency properties, one of the main topics
in this chapter.
Freezable is the base class for objects that can be frozen into a read-only state for performance reasons. Freezables,
once frozen, can be safely shared among multiple threads, unlike all other DispatcherObjects. Frozen objects can never
be unfrozen, but you can clone them to create unfrozen copies. Most Freezables are graphics primitives such as brushes,
pens, and geometries or animation classes.
.Visual is the base class for all objects that have their own 2D visual representation. Visuals are discussed in depth
in Chapter 15, 2D Graphics of the book.
UIElement is the base class for all 2D visual objects with support for routed events, command binding, layout, and
focus. These features are discussed in Chapter 5, Layout with Panels, and Chapter 6, Input Events: Keyboard,
Mouse, Stylus, and Multi-Touc. of the book.
Visual3D is the base class for all objects that have their own 3D visual representation. Visual3Ds are discussed in
depth in Chapter 16, 3D Graphics of the book.
UIElement3D is the base class for all 3D visual objects with support for routed events, command binding, and
focus, also discussed in Chapter 16.
ContentElement is a base class similar to UIElement but for document-related pieces of content that dont have
rendering behavior on their own. Instead, ContentElements are hosted in a Visual-derived class to be rendered on the
screen. Each ContentElement often requires multiple Visuals to render correctly (spanning lines, columns, and pages).
FrameworkElement is the base class that adds support for styles, data binding, resources, and a few common
mechanisms for Windows-based controls, such as tooltips and context menus.
FrameworkContentElement is the analog to FrameworkElement for content. Chapter 11, Images, Text, and Other
Controls, of the book examines the FrameworkContentElements in WPF.
Control is the base class for familiar controls such as Button, ListBox, and StatusBar. Control adds many properties
to its FrameworkElement base class, such as Foreground, Background, and FontSize, as well as the ability to be
completely restyled. Part III, Controls, examines WPFs controls in depth.
Lets discuss logical and visual trees.
Xaml good for UI because of hierarchical nature. Logical tree exists even if there is no xaml. Properties, events,
resources are tied to logical trees. Properties propagated down and events can be routed up or down the tree. Its a
simplification of whats actually going on when rendered. Visual tree can be thought of as an extension of the logical
tree though some things can be dropped as well. Visual tree exposes visual implementation details e.g. a listbox is
a border, two scrollbars and more. Only things from visual or visual3d appear in a visual tree. Avoid depending on
visual tree in your code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation " Title =" About WPF 4 Unl
< StackPanel >
< Label FontWeight =" Bold " FontSize ="20" Foreground =" White " > WPF 4 Unleashed
</ Label >
< Label >
2010 SAMS Publishing
</ Label >
< Label > Installed Chapters :
</ Label >
< ListBox >
< ListBoxItem > Chapter 1 </ ListBoxItem >
< ListBoxItem > Chapter 2 </ ListBoxItem >
</ ListBox >
< StackPanel Orientation =" Horizontal " HorizontalAlignment =" Center " >
< Button MinWidth ="75" Margin ="10" > Help </ Button >
< Button MinWidth ="75" Margin ="10" > OK </ Button >
</ StackPanel >
< StatusBar > You have successfully registered this product . </ StatusBar >
</ StackPanel >
</ Window >
using System ;
80
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Visual tree is empty until the dialog box is rendered. Navigating either can be done in instance methods of the
elements themselves e.g. visual class has protected members VisualParent, VisualChildrenCount, and GetVisualChild.
Frameworkelement and frameworkcontentelement have Parent property and LogicalChildren property.
81
82
Chapter 16
Lecture 16
Lets discuss dependency properties. They complicates .net types but once you realize the problem it solves, you realize
its importance. Dependency properties depends on multiple providers for determining its value at any point in time.
These providers can be an animation continuously changing its values. A parent whose property propagates down.
Arguably biggest feature is change notification. Motivation is to add rich functionality from declarative markup.
Key to declarative-friendly design is heavy use of properties. Button e.g. has 111 public properties (98 inherited).
Properties can be set using xaml, directly or in a design tool, without procedural code. Without the extra work in
dependency properties, it would be hard. We looked at implementation of a dependency property and then see its
benefits on top of .net properties. Change notification, property value inheritance, and support for multiple providers
are key features.
Understanding most nuances is important only for custom control authors. However what they are and how they
work important for everyone. Can only style and animate dependency properties. After using wpf for a while, one
wishes all properties were dependency properties. In practice, dependency properties are normal .net properties with
extra wpf infrastructure. No .net language other than xaml has an intrinsic understanding of dependency properties.
Lets look at a standard dependency property implementation.
1
2
3
83
84
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
< Button MouseEnter =" Button_MouseEnt er " MouseLeave =" Butt on_Mou seLeav e " MinWidth ="75" Margin ="10" >
< Button MouseEnter =" Button_MouseEnt er " MouseLeave =" Butt on_Mou seLeav e " MinWidth ="75" Margin ="10" >
1
2
3
4
// Change the foreground to blue when the mouse enters the button
void Button_Mo useEnt er ( object sender , MouseEventArgs e )
{
Button b = sender as Button ;
85
5
6
7
8
9
10
11
12
13
14
if ( b != null )
b . Foreground = Brushes . Blue ;
}
// Restore the foreground to black when the mouse exits the button
void Button_Mo useLea ve ( object sender , MouseEventArgs e )
{
Button b = sender as Button ;
if ( b != null )
b . Foreground = Brushes . Black ;
}
< Trigger Property =" IsMouseOver " Value =" True " >
< Setter Property =" Foreground " Value =" Blue "/ >
</ Trigger >
No need to worry about reverting but cannot be applied directly to button elements.
1
2
3
4
5
6
7
8
9
10
11
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation " Title =" About WPF 4 Unl
< StackPanel >
< Label FontWeight =" Bold " FontSize ="20" Foreground =" White " >
WPF 4 Unleashed
</ Label >
< Label >
2010 SAMS Publishing </ Label >
< Label > Installed Chapters : </ Label >
< ListBox >
< ListBoxItem > Chapter 1 </ ListBoxItem >
< ListBoxItem > Chapter 2 </ ListBoxItem >
</ ListBox >
< StackPanel Orientation =" Horizontal " HorizontalAlignment =" Center " >
< Button MinWidth ="75" Margin ="10" > Help </ Button >
< Button MinWidth ="75" Margin ="10" > OK </ Button >
</ StackPanel >
< StatusBar > You have successfully registered this product . </ StatusBar >
</ StackPanel >
</ Window >
It does not eect status bar. Not every dependency property participates in inheritance (Actually they can opt-in).
May be other higher priority sources setting property value. Some controls like status bar internally set their values
to system defaults. Property value inheritance in other places like to triggers inside a definition.
WPF contains many powerful mechanisms that independently attempt to set the value of dependency properties.
Dependency properties were designed to depend on these providers in a consistent and orderly manner. Its a 5 step
process.
86
step 1: determine base value. most providers factor into base value determination. highest to lowest precedence.
ten providers that can set value for most dep. props. 1. Local valueDependencyObject.SetValue, prop assignment in
xaml or2. Parent template trigger3. Parent template4. Style triggers5. Template triggers6. Style setters7. Theme
style triggers8. Theme style setters9. Property value inheritancealready seen10. Default valueinitial value registered
with the property. Thats why status bar did not get font propagated. use DependencyPropertyHelper.GetValueSource
to find which was the source used.
step 2: evaluate. Expressions need evaluation. It is used in data binding.
step 3: apply animation. Animations can alter value from step 2 or replace it.
step 4: coerce. The almost final value passed to CoerceValueCallback delegate if one is registered.
step 5: validate. Passed to ValidateValueCallback delegate. If one was registered. returning false causes exception
canceling the entire process.
wpf 4 adds new value in DependencyObject called SetCurrentValue. It updates current value without changing
value source.
Lets discuss attached properties now. They are special dependency properties that can be attached to arbitrary
objects. Sounds strange but there are many applications for it. There is new xaml syntax for attached props.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
Title =" About WPF 4 Unleashed " SizeToContent =" WidthAndHeight "
Background =" OrangeRed " >
< StackPanel >
< Label FontWeight =" Bold " FontSize ="20" Foreground =" White " >
WPF 4 Unleashed
</ Label >
< Label >
2010 SAMS Publishing </ Label >
< Label > Installed Chapters : </ Label >
< ListBox >
< ListBoxItem > Chapter 1 </ ListBoxItem >
< ListBoxItem > Chapter 2 </ ListBoxItem >
</ ListBox >
< StackPanel TextElement . FontSize ="30" TextElement . FontStyle =" Italic " Orientation =" Horizo
87
15
16
17
18
19
20
< Button MinWidth ="75" Margin ="10" > Help </ Button >
< Button MinWidth ="75" Margin ="10" > OK </ Button >
</ StackPanel >
< StatusBar > You have successfully registered this product . </ StatusBar >
</ StackPanel >
</ Window >
88
Chapter 17
Lecture 17
We discussed this example in the last lecture.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
Title =" About WPF 4 Unleashed " SizeToContent =" WidthAndHeight "
Background =" OrangeRed " >
< StackPanel >
< Label FontWeight =" Bold " FontSize ="20" Foreground =" White " >
WPF 4 Unleashed
</ Label >
< Label >
2010 SAMS Publishing </ Label >
< Label > Installed Chapters : </ Label >
< ListBox >
< ListBoxItem > Chapter 1 </ ListBoxItem >
< ListBoxItem > Chapter 2 </ ListBoxItem >
</ ListBox >
< StackPanel TextElement . FontSize ="30" TextElement . FontStyle =" Italic " Orientation =" Horizo
< Button MinWidth ="75" Margin ="10" > Help </ Button >
< Button MinWidth ="75" Margin ="10" > OK </ Button >
</ StackPanel >
< StatusBar > You have successfully registered this product . </ StatusBar >
</ StackPanel >
</ Window >
xaml parser requires setfontsize, setfontstyle on textelement and therefore equivalent code in C# is.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Enumeration values such as FontStyles.Italic, Orientation.Horizontal, and HorizontalAlignment.Center were previously specified in XAML simply as Italic, Horizontal, and Center, respectively. This is possible thanks to the
EnumConverter type converter C#. C# code shows no real magic, no .net property involved internally. There are
just calls to dependencyobject.setvalue and getvalue like normal property wrappers, must not go anything else.
89
90
1
2
3
4
5
6
7
8
9
We are setting the FontSize property by unrelated class TextElement. We could also have used TextBlock but
TextElement.FontSizeProperty is a separate DependencyProperty field from Control.FontSizeProperty.
1
2
3
4
5
6
Using RegisterAttached us optimized for attached property metadata. Control on the other hand just calls AddOwner.
1
2
3
These font related properties all controls inherit are from textelement in most cases, the class exposing the attached
property is the same that defines the normal dependency propery. Many dependency properties have a Tag property
for storing arbitrary custom data. A great mechanism for even extending sealed classes. In procedural code, you
can actually use any property by calling setvalue.
1
2
We can use this property any way we want but its better way to use Tag.
1
2
Its most commonly used for layout of UI elements. Various panel derived classes define attached properties designed
to be attached to their children. This way each panel can define custom behavior without burdening all possible children
with their own set of properties. It allows extensibility.
In summary, wpf could have exposed its features by apis but instead they focused on adding features to the core.
Multiple types of properties, multiple tree, multiple ways to achieve the same thing. Hopefully you can appreciate
the value in coming lectures. These concepts will fade in the background as we accomplish dierent tasks in coming
lectures.
Lets discuss sizing, positioning, and transforming elements. Sizing and positioning called layout. It boils down to
parent child relationships. They work together to determine their final sizes and positions. Parents tell where to render
and how much space they get. But more like collaborators they also ask children how much they really need. Panels
are parents supporting layout of multiple children. They derive from the abstract System.Windows.Controls.Panel
class. All the elements involved in the layout process derive from System.Windows.UIElement. Several properties
control various aspects of layout.
91
Size related properties are shown in blue, position related in red, green transforms can eect both. We will discuss
various panels that arrange their children in specific ways.
Lets first discuss size. Children tell their size to parents. wpf elements tend to size to content and no larger. Even
the whole window when you set SizeToContent property. All frameworkElements have Height and Width properties
of type double. Also have minheight, maxheight, minwidth, maxwidth. If explicit height width they take precedence
when in range (avoid explicit). min=0 and max=Infinity by default. NaN, Auto, Double.IsNan mean size to content.
Read only properties desiredSize, RenderSize, ActualHeight, ActualWidth. They are useful to act programatically on
final size.
Next is margin and padding. All framework elements have margin, controls (and Border) have padding. Margin is
extra space outside and padding is inside edges of the element. They are of type Thickness that can represent 1,
2, or 4 values. Negative margin is possible. labels default padding=5. Xaml specification is helped by typeconverter.
1
2
3
myLabel . Margin = new Thickness (10); //(10); // Same as Margin ="10" in XAML
myLabel . Margin = new Thickness (20 ,5 ,20 ,5); // Same as Margin ="20 ,5" in XAML
myLabel . Margin = new Thickness (0 ,10 ,20 ,30); // Same as Margin ="0 ,10 ,20 ,30" in XAML
The LengthConverter type converter associated with the various length properties supports specifying explicit units
of cm, pt, in, or px (the default). Default are device independent pixels. These logical pixels are 1/96 in regardless
of screen DPI setting. They are always stored as double. A typical display is 96 DPI. Important to note that all
measurements are DPI independent.
92
Next is Visibility. It can have three values: Visible The element is rendered and participates in layout, Collapsed
The element is invisible and does not participate in layout, Hidden The element is invisible yet still participates in
layout.
Compare the following two stackpanels.
1
2
3
4
5
6
7
8
9
Next is Position and alignmnet. Position is not given as (x,y), instead its parent controlled. Rather alignment and
flow direction is given vs. explicit height. HorizontalAlignment can taken values Left, Center, Right, and Stretch and
VerticalAlignment can take values Top, Center, Bottom, and Stretch.
1
2
3
4
5
6
Its only useful when parent gives more space than needed.
Control class also has HorizontalContentAlignment and VerticalContentAlignment. It sets how a control content
fills the space inside, more like the relationship between margin n padding. Default is left and top except button which
overrides it. Textblock doesnt strech like a control.
1
2
3
4
5
6
93
frameworkelement.FlowDirection can reverse the direction. It can be used for languages that are read right to left.
1
2
3
4
Transforms are from the base class System.Windows.Media.Transform. All framework elements have LayoutTransform and RenderTransform. One applied before layout and one after. UIElements have RenderTransformOrigin.
94
Chapter 18
Lecture 18
Lets revise size and position properties.
Layout transform vs render transform. One is applied before rendering and one after.
< Button Re nder Trans form Origi n ="0.5 ,0.5" Background =" Orange " >
< Button . RenderTransform >
< RotateTransform Angle ="45"/ >
</ Button . RenderTransform >
Rotated 45
</ Button >
Builtin transforms are Rotate Transform, Scale Transform, Skew Transform, Translate Transform, and Matrix
Transform. RotateTransform has Angle, CenterX, CenterY with defaults 0. Center useless for layout transform.
Center is also useful when grouping rendertransforms.
Transform can be on inner element.
95
96
1
2
3
4
5
6
7
8
Stretch and scaletransform only eect if more than stretch. Padding is scaled but margin is not. Does not eect
actualhieght actualwidth rendersize etc.
Skew Transform has AngleX Amount of horizontal skew (default value = 0), AngleY Amount of vertical skew
97
(default value = 0), CenterX Origin for horizontal skew (default value = 0), CenterY Origin for vertical skew
(default value = 0). It is applied as a render transform here.
Translate Transform has X Amount to move horizontally (default value = 0), Y Amount to move vertically
(default value = 0). It has no eect as a layout transform.
Matrix Transform has a single Matrix property (of type System.Windows.Media.Matrix) representing a 3x3 affine
transformation matrix.
1
1 ,0 ,0 ,1 ,10 ,20
/>
98
7
8
9
10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
Title =" Buttons in a Canvas " >
< Canvas >
< Button Background =" Red " > Left =0 , Top =0 </ Button >
< Button Canvas . Left ="18" Canvas . Top ="18"
Background =" Orange " > Left =18 , Top =18 </ Button >
< Button Canvas . Right ="18" Canvas . Bottom ="18"
Background =" Yellow " > Right =18 , Bottom =18 </ Button >
< Button Canvas . Right ="0" Canvas . Bottom ="0"
Background =" Lime " > Right =0 , Bottom =0 </ Button >
< Button Canvas . Right ="0" Canvas . Top ="0"
Background =" Aqua " > Right =0 , Top =0 </ Button >
< Button Canvas . Left ="0" Canvas . Bottom ="0"
Background =" Magenta " > Left =0 , Bottom =0 </ Button >
</ Canvas >
</ Window >
99
If left and right, right is ignored, top and bottom, bottom is ignored. Whats z order. Z-order decides which element
to show in overlapping elements.
1
2
3
4
Stack Panel is popular, simple, useful, stacks sequentially. It is one of the few panels that dont even define an
attached property. Orientation can be horizontal or vertical (which is default). Default horizontal direction is based
on FlowDirection.
Virtualizing panels e.g. VirtualizingStackPanel save space for oscreen content when data binding e.g. listbox uses
it
Wrap panel wraps to additional rows or columns when not enough space. It has no attached properties. Orientation
is by default horizontal. itemheight, itemwidth are uniform for all children and not set by default.
100
Chapter 19
Lecture 19
Dock panel allows easy docking of elements to an entire side. Dock attached property has left, right, top, bottom
values. Last child fills space unless LastChildFill=false.
1
2
3
4
5
6
7
101
102
103
We specify individual rows and cols. Its verbose but useful to specify details. Default is 1 cell. We position elements
using Row and Column attached properties (zero-based) default is 0,0. Multiple elements in same cell simply overlap
by z-order. Cells can be empty.
104
Online article list too small and and start page label not full width. We can make spanning rows and cols. RowSpan
and ColumnSpan 1 by default. By default height n width are same. Height and Width = Auto for sizing to content.
ShowGridLines = True to show grid lines.
For sizing rows and columns, use RowDefinition and Col. Height and Width not double but GridLength and not
default to Auto or NaN. Three types of sizing. Absoulte sizing: device independent pixels means no grow shrink,
Autosizing: size to content, or Proportional or star sizing: grows or shrinks. When 1 row col * all remaining space is
taken by it. When more row col * they divides remaining space. It can an be 2* or 5.5*. 2* is twice as * (1*). 5.5* is
twice as 2.75*. Remaining space is after absolute and autosized rows or cols. Default width and height are *.
105
1
2
3
4
GridLength
GridLength
GridLength
GridLength
length
length
length
length
=
=
=
=
new
new
new
new
GridLength (100);
GridLength (0 , GridUnitType . Auto );
GridLength (100 , GridUnitType . Pixel );
GridLength (2 , GridUnitType . Star );
Grid splitter is used for interactive sizing. Any number of gridsplitters can be added to a Grid. Can be used to move
entire row or column. Atleast one cell resizes and other cells behavior depends on weather absolute sizing or proportional
is applied on them. It fits in one cell, but behavior aects entire row or col so better to use span. Which cells are
aected depends on GridSplitters alignment values. Default horizontalalignment=right and verticalalignment=stretch.
Reasonable use requires stretch in one dimension.
When all proportionally sized, changes co-efficients accordingly. When absolute sizing, changes only top or left of
the cells. Remaining cells pushed down or right. Also has ResizeDirection (default Auto, or can be set to Rows or Cols)
and ResizeBehavior for explicit control. ResizeDirection eect only when stretching in both directions. ResizeBehavior
defaults to BasedOnAlignment. It can be set to PreviousAndCurrent, CurrentAndNext, or PreviousAndNext to control
which 2 rows or columns should be directly aected by resizing. Best way is to place it in its own autosized row or
column so it doesnt overlap existing content.
106
Chapter 20
Lecture 20
Lets revise grid.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SharedSizeGroup enables multiple row cols to remain the same width height when length changed via GridSplitter.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
107
108
IsSharedScope because sizegroups can be shared across multiple grids. All uses must be under a common parent
with issharedscope set to true. It is an attached property of grid as well.
Grid is usually the best choice. Except wraping, it can do what most panels do.
Content overflow can be dealt with Clipping, Scrolling, Scaling, Wrapping and Trimming. Wrapping already seen.
Only way for non-text to wrap is using wrappanel. Trimming is intelligent form of clipping. Supported for text by
TextBlock and AccessText. They have TextTrimming=None (default), or CharacterEllipsis, orWordEllipsis.
Clipping is default behavior. Edges of panel or cell area of dock area. All uielements have ClipToBounds. Controls
if it can draw outside bounds. Still cannot draw outside the window or page. Most panels clip regardless of this
property. canvas and uniformgrid dont unless this property is set. Button has this property false by default. Place
canvas inside a grid cell to avert clipping. Clipping is done before rendertransform. cant shrink back.
System.Windows.Controls.ScrollViewer control can be used for scrolling. Its content property is set and VerticalScrollBarVisibility and HorizontalScrollBarVisibility properties determine the display.
1
2
3
4
5
6
7
8
109
Scrolling more popular but e.g. card game needs scaling. Scaletransform works relative to their own size not the
available size. System.Windows.Controls.Viewbox, a type of class called Decorator (also Border). A panel-like thing
but has only one child. Stretches to fill available space by default but also Stretch=None (like not using it at all), Fill,
Uniform (aspect ratio, default), UniformToFill (cropped) StrechDirection=UpOnly, DownOnly, Both (default).
1
2
3
4
5
6
7
8
110
Chapter 21
Lecture 21
Lets make a visual studio like interface.
111
112
Because splitters are needed Grid is a reasonable idea. Three independent grids, because overlapping. Aharedsizegroup used to keep them in sync when docked.
When docking cells are added / removed. Z order between layer 1 and 2 so undocked is on top. All 3 placed in
another grid of single row col.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<! - - The bar of buttons docked along the right edge : -->
< StackPanel Name =" buttonBar " Orientation =" Horizontal " DockPanel . Dock =" Right " >
< StackPanel . LayoutTransform >
< RotateTransform Angle ="90"/ >
</ StackPanel . LayoutTransform >
< Button Name =" pane1Button " MouseEnter =" p a n e 1 B u t t o n _ M o u s e E n t e r " >
Toolbox
</ Button >
< Button Name =" pane2Button " MouseEnter =" p a n e 2 B u t t o n _ M o u s e E n t e r " >
Solution Explorer
</ Button >
</ StackPanel >
<! - - The Grid containing the three child Grids fills the DockPanel : -->
< Grid Name =" parentGrid " Grid . IsS haredS izeSco pe =" True " >
< Grid . ColumnDefinitions >
< ColumnDefinition Width ="5*"/ >
< ColumnDefinition Width ="364*"/ >
113
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
114
87
88
89
90
91
92
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using
using
using
using
System ;
System . Windows ;
System . Windows . Controls ;
System . Windows . Media . Imaging ;
115
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
116
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
Lets discuss Input Events now i.e. keyboard, mouse, stylus, multi-touch. We will start with routed events and
commands. Routed events are like dependency properties on top of .net properties. Similarly routed events are a
layer on top of .net events. They can travel up or down a visual or logical tree. Helps apps remain oblivious to the
visual tree. e.g. Button exposes Click based on MouseLeftButtonDown and KeyDown but actually ButtonChrome or
TextBlock visual child fires it. Event travels up the tree and Button eventually sees it. Or like in a previous example
rectangle on top of button. So arbitrary complex content but Click still raised. Otherwise would require custom code
on inner content or consumers. Very similar to dependency property concept.
Its an implementation, not a language feature other than xaml, like dependency properties. A handful of APIs.
public static RoutedEvent fields, and by convention Event suffix. Registered in the static ctor and a .net event wrapper.
(wrapper shouldnt do anything else).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
117
AddHandler, RemoveHandler, RaiseEvent are from UIElement not DependencyObject.
Routing Strategies include Tunneling: from root down to source or until marked handled, Bubbling: from source
to root or until marked handled, and Direct: only on source just like .net events but still participate in routed event
specific things like event triggers.
Handlers for routed events have a System.Object parameter (sender to which handler was attached), and System.EventArgs, and source which is the logical tree element that originally raised the event and originalSource which
is the element in visual tree that raised the event e.g. textblock on top of a button. RoutedEvent, actual routed event
object like Button.ClickEvent which is useful when same handler is used for multiple events.
There aer many keyboard, mouse, multi-touch, and stylus events. Most are bubbling events but many have a
tunneling counterpart. By convention tunneling event names are prefixed with Preview and come just before the
bubbling event comes. PreviewMouseMove comes before MouseMove. By convention, actions are only taken on
bubbling event so tunneling gives a chance to cancel or modify the event e.g. TextBox with restrictive input should
use previewKeyDown.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml "
x : Class =" AboutDialog " MouseRightBu t t o n D o w n =" A b o u t D i a l o g _ M o u s e R i g h t B u t t o n D o w n "
Title =" About WPF 4 Unleashed " SizeToContent =" WidthAndHeight "
Background =" OrangeRed " >
< StackPanel >
< Label FontWeight =" Bold " FontSize ="20" Foreground =" White " >
WPF 4 Unleashed
</ Label >
< Label >
2010 SAMS Publishing </ Label >
< Label > Installed Chapters : </ Label >
< ListBox >
< ListBoxItem > Chapter 1 </ ListBoxItem >
< ListBoxItem > Chapter 2 </ ListBoxItem >
</ ListBox >
< StackPanel Orientation =" Horizontal " HorizontalAlignment =" Center " >
< Button MinWidth ="75" Margin ="10" > Help </ Button >
< Button MinWidth ="75" Margin ="10" > OK </ Button >
</ StackPanel >
< StatusBar > You have successfully registered this product . </ StatusBar >
</ StackPanel >
</ Window >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using
using
using
using
System . Windows ;
System . Windows . Input ;
System . Windows . Media ;
System . Windows . Controls ;
118
22
23
24
25
26
27
28
Chapter 22
Lecture 22
Lets go over the code from last lecture again.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using
using
using
using
System . Windows ;
System . Windows . Input ;
System . Windows . Media ;
System . Windows . Controls ;
Note that we never receive an event on listbox item. Button has no border element so setting border has no eect.
Handling a halted event can only be done from procedural code.
Lets discuss attached events. Attached events can bubble and tunnel through elements who have not defined the
event. Like prop value inheritance and attach properties. Lets see a new example with window handling listbox
selectionchanged and button click events but does not define them.
1
2
3
4
5
6
7
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml "
x : Class =" AboutDialog " ListBox . SelectionChanged =" L i s t B o x _ S e l e c t i o n C h a n g e d "
Button . Click =" Button_Click "
Title =" About WPF Unleashed " SizeToContent =" WidthAndHeight "
Background =" OrangeRed " >
< StackPanel >
119
120
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
< Label FontWeight =" Bold " FontSize ="20" Foreground =" White " >
WPF 4 Unleashed
</ Label >
< Label >
2010 SAMS Publishing </ Label >
< Label > Installed Chapters : </ Label >
< ListBox >
< ListBoxItem > Chapter 1 </ ListBoxItem >
< ListBoxItem > Chapter 2 </ ListBoxItem >
</ ListBox >
< StackPanel Orientation =" Horizontal " HorizontalAlignment =" Center " >
< Button MinWidth ="75" Margin ="10" > Help </ Button >
< Button MinWidth ="75" Margin ="10" > OK </ Button >
</ StackPanel >
< StatusBar > You have successfully registered this product . </ StatusBar >
</ StackPanel >
</ Window >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Xaml valid because compiler sees relevant events defined in button and listbox at runtime however addhandler is
directly called. Equivalent code is:
1
2
3
4
5
6
7
public AboutDialog ()
{
I ni t i al i z eC o m po n e nt ();
this . AddHandler ( ListBox . SelectionChangedEvent ,
new S e l e c t i o n C h a n g e d E v e n t H a n d l e r ( L i s t B o x _ S e l e c t i o n C h a n g e d ));
this . AddHandler ( Button . ClickEvent , new RoutedEventHandler ( Button_Click ));
}
Theoretically one handler can do all event handling. We can use delegate contravariance i.e. arguments can be of
base type than delegate.
1
2
3
4
5
6
7
8
9
10
11
121
12
13
}
}
Lets discuss keyboard events keydown, keyup, and preview versions of them. KeyEventArgs contains Key, ImeProcessedKey, DeadCharProsessedKey, SystemKey, IsUp, IsDown, IsToggled, KeyStates, IsRepeat, and KeyboardDevice.
System.Windows.Input.Keyboard and its PrimaryDevice property are accessible everywhere.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
You can use keyboardDevice.IsKeyDown to even check if left or right alt is down etc. What is keyboard focus. UIElement Focusable property (true by default). FocusableChanged event, IsKeyboardFocused, IsKeyboardFocusWithin
(readonly). To set focus, use Focus or MoveFocus. IsKeyboardFocusedChanged, IsKeyboardFocusWithinChanged,
GotKeyboardFocus, LostKeyboardFocus, PreviewGotKeyboardFocus, and PreviewLostKeyboardFocus are intersting
events.
Mouse events are MouseEnter and MouseLeave (e.g. to create rollover eect however the preferred way is to use
trigger with IsMouseOver property or IsMouseDirectlyOver and IsMouseDirectlyOverChanged properties), MouseMove and PreviewMouseMove, MouseLeftButtonDown, MouseRightButtonDown, MouseLeftButtonUp, MouseRightButtonUp, and the more generic MouseDown and MouseUp, as well as the PreviewXXX versions of all six of these
events, MouseWheel and PreviewMouseWheel. If Visibility=Collapsed no mouse events are generated but opacity=0
generates all events. Null background fill stroke produce areas with no events however transparent or color does. So
null and transparent brush look same but dierent for hit test.
MouseEventArgs has 5 props of type MouseButtonState (Pressed or Released) LeftButton, RightButton, MiddleButton, XButton1, and XButton2. GetPosition function returning a Point with x and y props. Pass null for
screen relative position or an element for position with respect to that element. MouseWheel and PreviewMouseWheel get MouseWheelEventArgs derived from MouseEventArgs (add a Delta property). 12 events in mouse up down
get MouseButtonEventArgs adds a ChangedButton property, a ButtonState property (for the changed button) and a
ClickCount (clicks with time double click speed). Button base class raises a MouseDoubleClick by checking clickcount
in mouseleftbuttondown, similarly in preview versions.
For drag and drop, we have DragEnter, DragOver, DragLeave, with PreviewDragEnter, PreviewDragOver, and
PreviewDragLeave, Drop and PreviewDrop, QueryContinueDrag and PreviewQueryContinueDrag. Drag and drop
of clipboard content to/from elements not elements themselves. Its enabled by AllDrop=true. First two sets give
DragEventArgs with GetPosition, Data, Eects and AllowedEects (Copy, Move, Link, Scroll, All, None), KeyStates
(LeftMouseButton, RightMouseButton, MiddleMouseButton, ShiftKey, ControlKey, AltKey, or None) Continue evnets
are raised when a keyboard or mouse state changes during the operation and QueryContinueDragArgs has KeyStates,
EscapePressed, Action (Continue, Drop, Cancel).
To understand mouse capturing imagine drag and drop of elements. How to implement with MouseLeftButtonDown, MouseMove, and MouseLeftButtonUp. But mouse too fast or under another element. UIElements can
CaptureMouse and ReleaseMouseCapture. Properties IsMouseCaptured and IsMouseCaptureWithin, and the events
GotMouseCapture, LostMouseCapture, IsMouseCaptureChanged, and IsMouseCaptureWithinChanged are related to
capturing. Inside mouse move you can use a layout or rendertransform to move.
122
Stylus can behave like a mouse but has higher resolution, inverted, in air or not, pressure sensitivity. Similarly
multi-touch events are like mouse but not the other way around. There are available on win7 or later with multi-touch
hardware. We can either use basic touch events or higher level manipulation events.
Basic touch events are TouchEnter and TouchLeave, TouchMove and PreviewTouchMove, TouchDown, TouchUp,
PreviewTouchDown and PreviewTouchU, GotTouchCapture and LostTouchCapture. With multiple fingers, events
raised for each finger separately. For first finger mouse events are generated as well. TouchEventArgs has GetTouchPoint, GetIntermediateTouchPoints, TouchDevice. TouchPoint has Position, Size, Bounds, TouchDevice, Action
(Down, Up, Move). Each finger has its own touchDevice identified by Id porp.
Some notebooks support only two simultaneous touch points. Silverlight 4 doesnt support them. A lower level
FrameReported event that isnt even routed is however raised. Now lets discuss manipulation events for panning,
rotating, and zooming. They are easy to apply with a transform. Swipe easy with the other events as well but rotate
etc. difficult with previous events and lack of consistency in their behaviour between applications. Therefore using
the manipulation events is preferred.
Chapter 23
Lecture 23
Lets see an example using touch events.
1
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using
using
using
using
using
using
using
System ;
System . Collections . Generic ;
System . Windows ;
System . Windows . Controls ;
System . Windows . Input ;
System . Windows . Media ;
System . Windows . Media . Imaging ;
namespace TouchEvents
{
public partial class MainWindow : Window
{
// Keep track of which images are used for which TouchDevices
Dictionary < TouchDevice , Image > fingerprints =
new Dictionary < TouchDevice , Image >();
public MainWindow ()
{
I n it i a li z eC o m po n e nt ();
}
protected override void OnTouchDown ( TouchEventArgs e )
{
base . OnTouchDown ( e );
// Capture this touch device
canvas . CaptureTouch ( e . TouchDevice );
// Create a new image for this new touch
Image fingerprint = new Image {
Source = new BitmapImage ( new Uri (" pack :// application : , , ,/ fingerprint . png "))
123
124
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Manipulation events are ManipulationStarting and ManipulationStarted, ManipulationDelta, ManipulationCompleted. We combine information from multiple events. Manipulation events work if IsManipulationEnabled=true on
this or a parent and basic events not handled. Manipulation starting and started events at first finger touchdown, delta
at touchmove, and completed after touchup for all fingers. Starting and started events allow to customize or cancel or
disallow some manipulations. ManipulationDelta class has Translation, Scale, Rotation, Expansion (like Scale but dev
ind px instead of scale factor). ManipulationDeltaEventArgs has DeltaManipulation and CumulativeManipulation.
Lets see an example to move rotate zoom a photo.
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
125
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Manipulations always done relative to a manipulation container. By default element with ismanipulationenabled=true or handle ManipulationStarting event and set ManipulationStartingEventArgs.ManipulationContainer.
Now what is Inertia. ManipulationInertiaStarting event when all fingers loose contact even before a completed
event. By default manipulationcompleted thrown right away but you can set ManipulationInertiaStartingEventArgs.TranslationBehavior, RotationBehavior, and/or ExpansionBehavior which will cause deltas thrown and then
completed until inertia is completed. TranslationBehavior has DesiredDisplacement, DesiredDeceleration, and InitialVelocity. RotationBehavior has DesiredRotation, DesiredDeceleration, and InitialVelocity. ExpansionBehavior has
DesiredExpansion, DesiredDeceleration, InitialRadius, and InitialVelocity. Typically only set DesiredDeceleration or
the behavior-specific DesiredDisplacement, DesiredRotation, or DesiredExpansion. The latter properties are useful
for ensuring that the element doesnt go too far. By default, InitialVelocity and InitialRadius are initialized with the
current values. You can get the various velocities by checking ManipulationInertiaStartingEventArgs.InitialVelocities,
which has LinearVelocity, AngularVelocity, and ExpansionVelocity.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System ;
using System . Windows ;
using System . Windows . Input ;
using System . Windows . Media ;
namespace Ma ni pu la ti on Ev en ts
{
public partial class MainWindow : Window
{
public MainWindow ()
{
I n it i al i z eC o m po n e nt ();
canvas . Man ipulat ionDel ta += C a n v a s _ M a n i p u l a t i o n D e l t a ;
canvas . M a n i p u l a t i o n I n e r t i a S t a r t i n g += C a n v a s _ M a n i p u l a t i o n I n e r t i a S t a r t i n g ;
}
void C a n v a s _ M a n i p u l a t i o n I n e r t i a S t a r t i n g ( object sender , M a n i p u l a t i o n I n e r t i a S t a r t i n g E v e n t A
{
e . TranslationBehavior . D e si r e dD e c el e r at i o n = 0.01;
e . RotationBehavior . De si r e dD e c el e r at i o n = 0.01;
126
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
e . ExpansionBehavior . De si r e dD e c el e r at i o n = 0.01;
}
void C a n v a s _ M a n i p u l a t i o n D el t a ( object sender , M a n i p u l a t i o n D e l t a E v e n t A r g s e )
{
MatrixTransform transform = photo . RenderTransform as MatrixTransform ;
if ( transform != null )
{
// Apply any deltas to the matrix ,
// then apply the new Matrix as the MatrixTransform data :
Matrix matrix = transform . Matrix ;
matrix . Translate ( e . Del taMani pulati on . Translation .X , e . Delt aManipulation . Translat
matrix . RotateAt ( e . Del taMani pulati on . Rotation , e . M an ip ul at io nOr igin .X , e . Manipula
matrix . ScaleAt ( e . Del taMani pulati on . Scale .X , e . Del taManip ulatio n . Scale .Y , e . Manip
transform . Matrix = matrix ;
e . Handled = true ;
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
127
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System ;
using System . Windows ;
using System . Windows . Input ;
using System . Windows . Media ;
namespace SpinT hePrize Wheel
{
public partial class MainWindow : Window
{
public MainWindow ()
{
I n it i al i z eC o m po n e nt ();
grid . M a n i p u l a t i o n S t a rting += G r i d _ M a n i pu l a t i o n S t a r t i n g ;
grid . Man ipulat ionDel ta += G ri d_ Man ip ul ati on De lta ;
grid . M a n i p u l a t i o n I n e r t i a S t a r t i n g += G r i d _ M a n i p u l a t i o n I n e r t i a S t a r t i n g ;
grid . M a n i p u l a t i o n C o m plete d += G r i d _ M a n i p u l a t i o n C o m p l e t e d ;
}
void G r i d _ M a n i p u l a t i o n S t a r t i n g ( object sender , M a n i p u l a t i o n S t a r t i n g E v e n t A r g s e )
{
e . Mode = ManipulationModes . Rotate ; // Only allow rotation
}
void G r i d _ M a n i p u l a t i o n D e lta ( object sender , M a n i p u l a t i o n D e l t a E v e n t A r g s e )
{
( prizeWheel . RenderTransform as RotateTransform ). Angle +=
e . DeltaManipulation . Rotation ;
}
void G r i d _ M a n i p u l a t i o n I n e r t i a S t a r t i n g ( object sender , M a n i p u l a t i o n I n e r t i a S t a r t i n g E v e n t A r g
{
e . RotationBehavior . De si r e dD e c el e r at i o n = 0.001;
}
128
30
31
32
33
34
35
You can take advantage of panning support built into ScrollViewer by setting its PanningMode property to HorizontalOnly, VerticalOnly, HorizontalFirst, VerticalFirst, or Both. You can download the Surface Toolkit for Windows
Touch to get numerous slick Microsoft Surface WPF controls that are optimized for multi-touch. This includes surface
versions of most common controls (such as SurfaceButton and SurfaceCheckBox) and brand-new controls (such as
ScatterView and LibraryStack).
Chapter 24
Lecture 24
Commands are a more abstract and loosely coupled version of events e.g. cut copy paste commands. They are
exposed in various ways. They can be enabled disabled e.g. if there is nothing to paste. Two-way communication gets
cumbersome especially if you dont want the list of controls hard-coded.
WPF defines a number of built-in commands. Commands have automatic support for input gestures (such as
keyboard shortcuts). Some of WPFs controls have built-in behavior tied to various commands.
Any object implementing ICommand which defines Execute, CanExecute, CanExecuteChanged can work as a
Command. For Cut, Copy, and Paste, you could define and implement three classes implementing ICommand, find a
place to store them (perhaps as static fields of the main Window), call Execute from relevant event handlers (when
CanExecute returns true), and handle the CanExecuteChanged event to toggle the IsEnabled property on the relevant
pieces of user interface. Controls have logic to interface with commands through Command property. We can also do
it all in xaml.
Following are pre-defined builtin commands. ApplicationCommands e..g Close, Copy, Cut, Delete, Find, Help, New,
Open, Paste, Print, PrintPreview, Properties, Redo, Replace, Save, SaveAs, SelectAll, Stop, Undo, and more. ComponentCommands e.g. MoveDown, MoveLeft, MoveRight, MoveUp, ScrollByLine, ScrollPageDown, ScrollPageLeft,
ScrollPageRight, ScrollPageUp, SelectToEnd, SelectToHome, SelectToPageDown, SelectToPageUp, and more. MediaCommands e.g. ChannelDown, ChannelUp, DecreaseVolume, FastForward, IncreaseVolume, MuteVolume, NextTrack, Pause, Play, PreviousTrack, Record, Rewind, Select, Stop, and more. NavigationCommands e.g. BrowseBack,
BrowseForward, BrowseHome, BrowseStop, Favorites, FirstPage, GoToPage, LastPage, NextPage, PreviousPage, Refresh, Search, Zoom, and more. EditingCommands e.g. AlignCenter, AlignJustify, AlignLeft, AlignRight, CorrectSpellingError, DecreaseFontSize, DecreaseIndentation, EnterLineBreak, EnterParagraphBreak, IgnoreSpellingError,
IncreaseFontSize, IncreaseIndentation, MoveDownByLine, MoveDownByPage, MoveDownByParagraph, MoveLeftByCharacter, MoveLeftByWord, MoveRightByCharacter, MoveRightByWord, and more.
All instances of RoutedUICommand implement ICommand and support bubbling.
1
If you run it would be always disabled. We need to add CommandBinding to the element or a Parent (bubbling).
All UIElements have CommandBindings collection.
1
2
3
4
5
6
7
8
1
2
3
4
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml "
x : Class =" AboutDialog "
Title =" About WPF Unleashed " SizeToContent =" WidthAndHeight "
129
130
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
1
2
131
Controls with builtin command bindings e.g. textbox that responds to ctrl-z etc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
< StackPanel xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml "
Orientation =" Horizontal " Height ="25" >
< Button Command =" Cut " CommandTarget ="{ Binding ElementName = textBox }"
Content ="{ Binding RelativeSource ={ RelativeSource Self } , Path = Command . Text }"/ >
< Button Command =" Copy " CommandTarget ="{ Binding ElementName = textBox }"
Content ="{ Binding RelativeSource ={ RelativeSource Self } , Path = Command . Text }"/ >
< Button Command =" Paste " CommandTarget ="{ Binding ElementName = textBox }"
Content ="{ Binding RelativeSource ={ RelativeSource Self } , Path = Command . Text }"/ >
< Button Command =" Undo " CommandTarget ="{ Binding ElementName = textBox }"
Content ="{ Binding RelativeSource ={ RelativeSource Self } , Path = Command . Text }"/ >
< Button Command =" Redo " CommandTarget ="{ Binding ElementName = textBox }"
Content ="{ Binding RelativeSource ={ RelativeSource Self } , Path = Command . Text }"/ >
< TextBox x : Name =" textBox " Width ="200"/ >
</ StackPanel >
Button and textbox have no direct knowledge of each other. Through commands we have a rich interaction. The
more the standardization on builtin commands, the more seamless and declarative the interaction can be between
controls.
In summary, wpf input events make possible rich interactive content. We focused on UIElement but the same
events can be used with ContentElement.
132
Chapter 25
Lecture 25
Lets discuss structuring and deploying an application. A standard windows app or partial trust web app or loose xaml.
We will discuss Photo Gallery example with the book. App.xaml and MainWindow.xaml and code-behind files on a new
wpf project. WPF Window is a win32 window, same chrome (non-client area) same taskbar behavior etc. Icon Title
WindowStyle TopMost ShowInTaskbar properties. Left and Top props or WindowStartupLocation=CenterScreen or
CenterOwner. Any number of child windows can be made by instantiating a Window dervied class and calling Show.
Child window like parent window but gets closed when parent and similarly minimized, also called modeless dialog.
Another windows Owner property after parent shown, OwnedWindows property. There are Activated & Deactivated
events. Activate method (like SetForegroundWindow). ShowActivated=false, initially not shown.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
133
134
35
36
37
38
End result same whether you attach event handler or override this method. Technically a bit faster and more neat
when subclass wants to handle something base class throws. DispatcherObject cant be accessed from a dierent thread
which avoids many issues. App terminating, you need to add a message loop to process windows messages and pass
them to the correct window.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1
2
3
4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[ STAThread ]
Public static void Main ()
{
Application app = new Application ();
MainWindow window = new MainWindow ();
window . Show ();
app . Run ( window );
}
[ STAThread ]
Public static void Main ()
{
Application app = new Application ();
app . StartupUri = new Uri (" MainWindow . xaml " , UriKind . Relative );
app . Run ();
}
< Application x : Class =" PhotoGallery . App "
xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml "
StartupUri =" MainWindow . xaml "/ >
using System . Windows ;
namespace PhotoGallery
{
public partial class App : Application
{
public App ()
{
I n it i a li z eC o m po n e nt ();
}
}
}
Main ()
[ System . ST AThreadAttribute ()]
public static void Main ()
{
PhotoGallery . App app = new PhotoGallery . App ();
app . In itializeComponent ();
app . Run ();
}
App code-behind can be omitted altogether. But where is main. app.xaml is assigned ApplicationDefinition which
causes App.g.cs to be generated and can be seen in Solution Explorer if you Show all files. System.Environment.GetCommandLineAr
or set build action to Page and write Main. Startup, Exit, Activated, Deactivated (any window), SessionEnding (cancellable logo shutdown). A read-only Windows collection, MainWindow property (read-write). ShutdownMode (when
to end the app). Properties dictionary for sharing between windows. Application.Current from any window.
Lets discuss creating a single instance app. Can create app without Application using Dispatcher.Run or Win32
message loop but explicit termination and other issues. One UI Thread and one render thread. Can create more with
Dispatcher.Run which can improve responsiveness. Can schedule on UI thread with Dispatcher.Invoke and BeginInvoke
and priority from send (now) to systemidle.
135
1
2
3
4
5
6
7
8
9
bool mutexIsNew ;
using ( System . Threading . Mutex m =
new System . Threading . Mutex ( true , uniqueName , out mutexIsNew ))
{
if ( mutexIsNew )
// This is the first instance . Run the application .
else
// There is already an instance running . Exit !
}
You can also create a splash screen. Nothing fancy because wpf not loaded yet. In wpf project - add new item splash screen, adds an images with build action SplashScreen.
Modal dialogs include common dialogs which are actually provided by win32. Instantiate, call ShowDialog and
process result.
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
A window to be shown as a dialog sets its dialogResult to bool. Setting it closes window or set Buttons IsDefault
prop to true.
1
2
3
4
1
2
3
4
5
6
[ STAThread ]
public static void Main ()
{
MainWindow window = new MainWindow ();
window . ShowDialog ();
}
136
Lets discuss persisting and restoring. Can use registry or file system but lets use .net isolated storage. Physically
located in the users document folder in a hidden folder. VS generated Settings class provide an even easier and strongly
typed way but in a app. config file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Lets discuss clickonce vs. windows installer. VS setup and deployment projects or a simpler clickonce wizard from
build-publish menu. Windows installer benefits include showing custom setup UI like a EULA, control over where files
installed, arbitrary code at setup time, install shared assemblies in global assembly cache, register COM components
and file associations, install for all users, oine installation from cd.
clickonce benefits include builtin support for automatic updates and rollback to prev versions, a web-like go-away
experience or start menu and control panel program list, all files in isolated area, so no eect on other apps, clean
uninstallation, but full trust apps can do things while they run, .net code access security, partial trust.
Chapter 26
Lecture 26
Lets discuss navigation based apps like windows explorer, media player, photo gallery. Can use navigation support
for a wizard or organize the whole ui around navigation. With nav, content is usually in Page a simpler version of
Window. Then hosted in a NavigationWindow or a Frame. They provide support for navigating, a history journal,
and nav related events. NavigationWindow more like a top-level window whereas Frame more like an HTML frame or
iframe By default navWind has a bar on top with back/fwd, frame doesnt but can be shown.
1
2
3
4
5
6
7
8
9
< NavigationWindow
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"
mc : Ignorable =" d " x : Class =" PhotoGallery . Container "
Title =" Photo Gallery " Source =" MainPage . xaml "
d : DesignWidth ="1320" d : DesignHeight ="919"
/>
nav enabled version points startup uri to this and and mainpage.xaml referenced above has the content.
1
2
3
4
5
6
page does everything window does except onclosed and onclosing. with these changes, nothing much changes in
our app, just some disabled back/fwd buttons. navigation can also happen between html files.
A Page can interact with its navigation container by using the NavigationService class, which exposes relevant
functionality regardless of whether the container is a NavigationWindow or a Frame. You can get an instance of
NavigationService by calling the static NavigationService.GetNavigationService method and passing the instance of
the Page. But even more easily, you can simply use Pages NavigationService property. For example, you can set a
title that is used in the drop-down menu associated with the Back and Forward buttons as follows:
1
Main
Photo Gallery
Page
But Page also contains a few of its own properties that control the behavior of the parent container, such as
WindowHeight, WindowWidth, and WindowTitle. Can also set in xaml. You can perform navigation in three main
ways: Calling the Navigate method, Using Hyperlinks, Using the journal. Navigation containers support a Navigate
method.
1
2
137
138
3
4
5
this . Navigatio nServi ce . Navigate ( new Uri (" http :// www . adamnathan . net / wpf "));
Hyperlink element is used to link to xaml. or handle its Click event and call navigate yourself to link from html to
wpf. handle Navigating event and look for a sentinel HREF value can also set TargetName to update a frame or use
# and any named element in a page.
1
2
3
4
Lets discuss using Journal. journal provides logic behind back and fwd. internally two stacks. back / fwd moves
pages between stacks. any other action empties the fwd stack. back fwd can also nav. containers GoBack and
GoForward and CanGoBack/fwd to avoid exception. nav. wnd. always has journal but frame may depending on
its JournalOwnership=OwnsJournal, UsesParentJournal, Automatic (parent when hosted in wnd or frame). When
frame has journal it has back/fwd buttons but can set NavigationUIVisibility=Hidden. when nav. with URI or
hyperlink, always new instance. can control when calling navigate with page so work to remember state. However,
JournalEntry.KeepAlive attached prop. can help for back fwd. RemoveFromJournal means a page is not in journal.
other purposes of journal e.g. application specific undo redo scheme. nav. container AddBackEntry and pass
CustomContentState abstract class with a Replay method that must be defined. optionally JournalEntryName can
be set. we use this in photo gallery for undoable image rotation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[ Serializable ]
class RotateState : Cu st om Co nt en tState
{
FrameworkElement element ;
double rotation ;
public RotateState ( FrameworkElement element , double rotation )
{
this . element = element ;
this . rotation = rotation ;
}
public override string JournalEntryName
{
get { return " Rotate " + rotation + " "; }
}
public override void Replay ( Nav igatio nServi ce navigationService , NavigationMode mode )
{
// Rotate the element by the specified amount
element . LayoutTransform = new RotateTransform ( rotation );
}
}
139
NavigationStopped is an event called instead of LoadCompleted if an error occurs or nav. is cancelled. these events
also defined in Application to handle for any nav. cont. html to html nav. not in journal, no event raised.
To send data to pages, Navigate overloads with an extra object param. target page receives it in loadcompleted.
1
2
3
4
5
6
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
140
1
2
3
4
5
6
7
8
9
10
< PageFunction
xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml "
xmlns : sys =" clr - namespace : System ; assembly = mscorlib "
x : Class =" MyProject . PageFunction1 "
x : TypeArguments =" sys : String "
Title =" PageFunction1 " >
< Grid >
</ Grid >
</ PageFunction >
1
2
3
4
5
6
7
8
9
10
Chapter 27
Lecture 27
Lets discuss XAML Browser apps (XBAPS). silverlight more popular to deliver partial-trust wpf content in a browser.
dierences are that not all features available by default, nav is integrated into the browser, deployment dierent.
In VS, create WPF browser application. create UI in Page and compile and run. really just online-only clickOnce
applications, with some special wpf handling for browser-integrated experience.
1
2
clickonce caching. VS increments. or you can clear cache. change some settings and its a xbap. but partial trust
restricts many api. e.g. above call exception. requires FileIOPermission which is not by default. hit n trial to find
what works. local registry and file system, new windows (popups ok), unmanaged, but others dependent on browser,
or on implementation details. BrowserInteropHelper.IsBrowserHosted property to check if its a XBAP.
1
2
3
4
5
6
7
8
9
10
but u can still use rich text and media, isolated storage upto 512kb, arbitrary files on host web server, use browser
file open dialog for local files. how parameters passed in. either BrowserInteropHelper.Source to retrieve the complete
URL or browser cookie retrieved by Application.GetCookie method. any assembly marked with AllowPartiallyTrustedCallers and placed in GAC can be called by partial-trust code and it can be security loophole too.
There are also full-trust browser apps. In the project file you change
1
to this:
1
< PermissionSet class =" System . Security . PermissionSet " version ="1"
ID =" Custom " SameSite =" site " Unrestricted =" true "/ >
You get Integrated Navigation in XBAP. Many XBAP dont take advantage of navigation. Such applications can
set ShowNavigationUI=false on Page. IE 7 and later merge the journal and provide a more streamlined interface.
However if it appears in an IFrame, there is still a separate nav. bar. To publish, use VS publishing wizard or mage
tool in SDK and copy files to webserver which must be configured to serve it. Users can install and run by just
navigating to a URL. No security prompt if you dont need non. Stdandard permissions.
141
142
Lets discuss downloading files on demand. We will assign a set of loose files to a download group in VS. Under
publish-application files in proj. prop. Then use api in System.Deployment.Application to prompt download and be
notified e.g. progress bar while app loads. Page1 starts, loads MyGroup and shows page2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System ;
using System . Windows . Controls ;
using System . Windows . Threading ;
using System . Deployment . Application ;
public partial class Page1 : Page
{
public Page1 ()
{
I ni t i al i z eC o m po n e nt ();
}
protected override void OnInitialized ( EventArgs e )
{
base . OnInitialized ( e );
if ( Ap plic ation Depl oymen t . IsN etwork Deploy ed )
{
A p p l i c a t i o n D e p l o y m e n t . CurrentDeployment . D o w n l o a d F i l e G r o u p C o m p l e t e d +=
delegate {
Dispatcher . BeginInvoke ( DispatcherPriority . Send ,
new D i s p a t c h e r O p e r a t i o n C a l l b a c k ( GotoPage2 ) , null );
};
A p p l i c a t i o n D e p l o y m e n t . CurrentDeployment . D own lo ad Fil eG ro upA sy nc (" MyGroup ");
}
else
{
GotoPage2 ( null );
}
}
private object GotoPage2 ( object o )
{
return Na vigatio nServi ce . Navigate ( new Uri (" Page2 . xaml " , UriKind . Relative ));
}
}
Additional events can be used for fine grained progress. Loose xaml is powerful sometimes instead of html. In
summary, XBAP have similar impl. from desktop app to web app. Deployment just needs the right .net installed.
wpf 3.5 by default on win7, wpf4 now.
Lets discuss resources e.g. bitmap, fonts, string tables. Wpf builds on top, has binary resources and logical
resources. Binary resources are what rest of .net framework considers a resource. Even compiled xaml stored as a
resource. Can be embedded in assembly, loose file that may or may not be known at compile time. Can be localizable
or not.
To define a binary resource, add a file and set the build action resource or content (loose file).
143
Dont use embeddedresource. Its misleading name but wpf doesnt fully support. Adding as content and loading
directly are kind of equal but resource is neat. Should be embed if localizable or single binary file benefits.
Lets see how to assign binary resource whether embed or loose. Wont work if not added to proj. If not added be
explicit about the path.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
< StackPanel Grid . Column ="1" Orientation =" Horizontal " HorizontalAlignment =" Center " >
< Button x : Name =" previousButton " ToolTip =" Previous ( Left Arrow )" >
< Image Height ="21" Source =" previous . gif "/ >
</ Button >
< Button x : Name =" slideshowButton " ToolTip =" Play Slide Show ( F11 )" >
< Image Height ="21" Source =" slideshow . gif "/ >
</ Button >
< Button x : Name =" nextButton " ToolTip =" Next ( Right Arrow )" >
< Image Height ="21" Source =" next . gif "/ >
</ Button >
</ StackPanel >
< Image Height ="21" Source =" pack :// siteOfOrigin : , , ,/ slideshow . gif "/ >
Image image = new Image ();
image . Source = new BitmapImage ( new Uri (" pack :// application : , , ,/ logo . jpg "));
Can use subfolders for embedded resources. From procedural code, cant use xaml spec. so there are shortcuts.
144
Chapter 28
Lecture 28
Lets discuss localizing binary resources. can partition into satellite assembly and use LocBaml to manage string
localization. To spec. a default culture and auto. build a satellite assembly, you can to set UICulture. Need to
open project file in a text ed. add under debug, release etc. or where it eects all prop. If you rebuild your project
with this setting in place, youll find an en-US folder alongside your assembly, containing the satellite assembly named
AssemblyName.resources.dll. Also mark assembly with the neutral resource language matching.
1
2
3
4
5
< Project
>
< PropertyGroup >
< UICulture > en - US </ UICulture >
[ assembly : N e u t r a l R e s o u r c e s L a n g u a g e (" en - US " ,
U l t i m a t e R e s o u r c e F a l l b a c k L o c a t i o n . Satellite )]
next, apply Uid directive to any element needing localization. msbuild /t:updateuid ProjectName.csproj. LocBaml
/parse ProjectName.g.en-US.resources /out:en-US.csv. now edit and localize all strings. LocBaml /generate ProjectName.resources.dll /trans:fr-CA.csv /cul:fr-CA. then copy the assembly with a name matching the locale. to test, System.Threading.Thread.CurrentThread.CurrentUICulture (and System.Threading.Thread.CurrentThread.CurrentCulture)
to an instance of the desired CultureInfo.
Logical resources are introduced by wpf. arbitrary .net object stored and named in an elements Resources prop.
typically meant to be shared by multiple child objects. FrameworkElement and FrameworkContentElement both have
a Resources prop. often are style or data providers. first examples using simple brushes. much like css, share objects.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
Title =" Simple Window " Background =" Yellow " >
< DockPanel >
< StackPanel DockPanel . Dock =" Bottom "
Orientation =" Horizontal "
H or i z on t a lA l ignment =" Center " >
< Button Background =" Yellow "
BorderBrush =" Red " Margin ="5" >
< Image Height ="21" Source =" zoom . gif "/ >
</ Button >
< Button Background =" Yellow "
BorderBrush =" Red "
Margin ="5" >
< Image Height ="21"
Source =" d e f a u l t T h u m b n a i l S i z e . gif "/ >
</ Button >
< Button Background =" Yellow "
BorderBrush =" Red "
Margin ="5" >
< Image Height ="21"
Source =" previous . gif "/ >
</ Button >
145
146
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
147
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
< Image Height ="21" Source =" previous . gif "/ >
</ Button >
< Button Background ="{ StaticResource backgroundBrush }"
BorderBrush ="{ StaticResource borderBrush }" Margin ="5" >
< Image Height ="21" Source =" slideshow . gif "/ >
</ Button >
< Button Background ="{ StaticResource backgroundBrush }"
BorderBrush ="{ StaticResource borderBrush }" Margin ="5" >
< Image Height ="21" Source =" next . gif "/ >
</ Button >
< Button Background ="{ StaticResource backgroundBrush }"
BorderBrush ="{ StaticResource borderBrush }" Margin ="5" >
< Image Height ="21" Source =" counterclockwise . gif "/ >
</ Button >
< Button Background ="{ StaticResource backgroundBrush }"
BorderBrush ="{ StaticResource borderBrush }" Margin ="5" >
< Image Height ="21" Source =" clockwise . gif "/ >
</ Button >
< Button Background ="{ StaticResource backgroundBrush }"
BorderBrush ="{ StaticResource borderBrush }" Margin ="5" >
< Image Height ="21" Source =" delete . gif "/ >
</ Button >
</ StackPanel >
< ListBox / >
</ DockPanel >
</ Window >
< Li ne arG radientBrush x : Key =" backgroundBrush " StartPoint ="0 ,0" EndPoint ="1 ,1" >
< GradientStop Color =" Blue " Offset ="0"/ >
< GradientStop Color =" White " Offset ="0.5"/ >
< GradientStop Color =" Red " Offset ="1"/ >
</ LinearGradientBrush >
now u can change brushes in one place and have dierent eects. StaticResource markup extension walks the
logical tree or even application level or system resources. root level or app level resource dict for max sharing. closest
to element chosen. for multi-threaded either Frozen or x:Shared=false.
148
Lets discuss static vs Dynamic Resources. DynamicResource reapplied every time it changes nothing special about
the resources. only if you want to see updates or not. dynamic more overhead but demand loaded. dynamic can only
be used to set dep. prop. values. static can even abstract whole controls.
1
2
3
4
5
6
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml " >
< Image Height ="21" Source =" zoom . gif "/ >
</ Window >
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml " >
< Window . Resources >
< Image x : Key =" zoom " Height ="21" Source =" zoom . gif "/ >
</ Window . Resources >
< StackPanel >
< StaticResource ResourceKey =" zoom "/ >
</ StackPanel >
</ Window >
can be a way to factor but Image can only have one parent so cant share last, static doesnt support fwd. ref. with
dyn. the following is possible.
1
2
3
4
5
6
7
8
9
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml "
Title =" Simple Window " Background ="{ DynamicResource backgroundBrush }" >
< Window . Resources >
< SolidColorBrush x : Key =" backgroundBrush " > Yellow </ SolidColorBrush >
< SolidColorBrush x : Key =" borderBrush " > Red </ SolidColorBrush >
</ Window . Resources >
</ Window >
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml " >
< Window . Resources >
< Image x : Shared =" False " x : Key =" zoom " Height ="21" Source =" zoom . gif "/ >
</ Window . Resources >
< StackPanel >
<! - - Applying the resource multiple times works ! -->
< StaticResource ResourceKey =" zoom "/ >
< StaticResource ResourceKey =" zoom "/ >
< StaticResource ResourceKey =" zoom "/ >
</ StackPanel >
</ Window >
On in procedural code
1
2
3
4
5
6
7
8
9
10
window . Resources . Add (" backgroundBrush " , new SolidColorBrush ( Colors . Yellow ));
window . Resources . Add (" borderBrush " , new SolidColorBrush ( Colors . Red ));
Button button = new Button ();
// The Button must descend from the Window before looking up resources :
stackPanel . Children . Add ( button );
button . Background = ( Brush ) button . FindResource (" backgroundBrush ");
button . BorderBrush = ( Brush ) button . FindResource (" borderBrush ");
Button button = new Button ();
149
11
12
13
14
15
16
17
XAML :
< Button Background =" SystemColors . WindowBrush "/ >
C \#:
button . Background = ( Brush ) new
BrushConverter (). ConvertFrom (" SystemColors . WindowBrush ");
XAML :
< Button Background =" { x : Static SystemColors . WindowBrush }"/ >
C \#:
button . Background = SystemColors . WindowBrush ;
XAML :
< Button Background =" { StaticResource SystemColors . WindowBrushKey }"/ >
C \#:
button . Background = ( Brush ) FindResource (" SystemColors . WindowBrushKey ");
XAML :
< Button Background =" { StaticResource { x : Static SystemColors . WindowBrush }}"/ >
C \#:
button . Background = ( Brush ) FindResource ( SystemColors . WindowBrush );
XAML :
< Button Background =" { StaticResource { x : Static SystemColors . WindowBrushKey }}"/ >
C \#:
button . Background = ( Brush ) FindResource ( SystemColors . WindowBrushKey );
XAML :
< Button Background =" { DynamicResource { x : Static SystemColors . WindowBrushKey }}"/ >
C \#:
button . S e t Re s o u r c e R e f e r e n c e (
Button . BackgroundProperty , SystemColors . WindowBrushKey );
In summary, resources really imp. in professional apps, enable localization, increase productivity as it consolidates
/ shares. Most interesting use is with styles and data binding.
150
Chapter 29
Lecture 29
We will discuss data binding now. data means an arbitrary .net obj. data binding, data templates, data triggers are
related concepts. data can be collection obj, xml file, web service, db table, custom obj, even wpf element eg button.
So data binding is typing together arbitrary objects. Classic scenario is a visual rep. (e.g. listbox or datagrid) of
items in an xml file, db, or in-memory collection. Instead of iterating and adding items, tell listbox to get its data
from another source, keep them up to date, format them etc.
Binding binds two properties together and keeps a communication channel open. setup Binding once and let it
handle all the sync. eg. in proc. code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
< TextBlock x : Name =" currentFolder " DockPanel . Dock =" Top "
Background =" AliceBlue " FontSize ="16" / >
void t r e e V i e w _ S e l e c t e d I t e m C h a n g e d ( object sender ,
RoutedPropertyChangedEventArgs < object > e )
{
currentFolder . Text =
( treeView . SelectedItem as TreeViewItem ). Header . ToString ();
Refresh ();
}
public MainWindow ()
{
I ni t i al i z eC o m po n e nt ();
Binding binding = new Binding ();
// Set source object
binding . Source = treeView ;
// Set source property
binding . Path = new PropertyPath (" SelectedItem . Header ");
// Attach to target property
currentFolder . SetBinding ( TextBlock . TextProperty , binding );
}
when an item with no header selected, then a default value ( in this case) returned. no exception is raised. binding
has a source prop and a target prop. source is an object and a prop. path. can also use BindingOperations.SetBinding.
BindingOperations.ClearBinding. BindingOperations.ClearAllBindings. or set the target prop to a new val. (but clear
would allow receiving values from lower prop. sources).
There is a binding markup extension as well.
1
2
3
4
5
6
7
< TextBlock x : Name =" currentFolder " DockPanel . Dock =" Top "
Text ="{ Binding ElementName = treeView , Path = SelectedItem . Header }"
Background =" AliceBlue " FontSize ="16" / >
< TextBlock x : Name =" currentFolder " DockPanel . Dock =" Top "
Text ="{ Binding Source ={ x : Reference TreeView } , Path = SelectedItem . Header }"
Background =" AliceBlue " FontSize ="16" / >
< TextBlock Text ="{ Binding
TargetNullValue = Nothing is selected .}"
/>
151
152
8
9
10
11
12
13
14
could also set Source but using ElementName is easier. can also set value for nothing is selected.
We can also bind to plain .net properties. but the source obj should implement the System.ComponentModel.INotifyPropertyCh
interface, which has a single PropertyChanged event. (the right way) and Implement an XXXChanged event, where
XXX is the name of the property whose value changed. public class Photos : ObservableCollectionPhoto target must
be a dep. prop. When binding to an object, Path is optional
1
2
3
4
>
We can also bind to a collection. how abt binding listbox in photo app to photo collection. when a new dir
selected, clear lisbox and created listboxitem for each item. when user del or rename, an event (because of filesystemwatcher) and manually refresh. raw binding i.e. Items is not dep. prop but ItemSource is. source prop must impl.
INotifyCollectionChanged (aka ObservableCollection). The simplest e
< ListBox x : Name =" pictureBox " Dis playMemberPath =" Name "
153
2
3
4
>
We cant mix Items and ItemSource. But we always retrieve from Items. We could add an Image property but
there are more flexible ways. 2 ways: data template and value converter. selected item can also be synchronized but
scrolling not synchronized, only first selection synchronized.
1
2
3
4
5
6
Implicit data source is provided by a Data Context. We set DataContext of a parent and then dont specify Source
or ElementName or set parent.DataContext = photos;. It is useful when plugging in resources: usage context or decl.
context.
1
2
3
4
5
6
7
8
9
10
Control rendering is easy without binding but there are benefits of data binding. WPF gives three ways. string
formatting which only works if the target prop is a string. {} to escape. can add 1000 seperator etc.
1
2
3
4
5
6
7
8
9
10
11
154
12
1
2
3
4
5
6
7
With Data Template, UI auto-applied to arbitrary .net object when it is rendered. by setting these prop. you can
swap in a complete new visual tree easy in xaml, cumbersome in proc. code try with photo gallery
1
2
3
4
5
6
7
8
9
>
155
with a template there is implicit dataContext. template can be used on non-data bound but inside the element it
almost always make sense to use data binding. template can be shared as resources. template can even be auto-applied
to some type by setting its DataType prop. there is also HierarchicalDataTemplate that understands hierarchies. can
be used with Treeview or menu.
1
2
3
4
5
6
7
8
9
>
Value Convertors morph source value into something else. introduce custom logic and can change type etc. e.g.
brush based on some enumeration. can be used to customize display.
1
2
3
4
5
6
7
8
9
156
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Chapter 30
Lecture 30
In last lecture, we discused data binding, binding object, markup extension, bind to any prop with INotifyPropertyChanged, target must be dependency property, bind to obj. so no property path, binding to collection, issynchronized
with current item, datacontext, displaymemberpath, stringformat, datatemplate, valueconverter.
Lets discuss customizing collection view. when isSynchronizedWithCurrentItem= true, where is the current item.
a default view inserted. object implementing ICollectionView. has also support for sorting, grouping, filtering, and
navigating. lets discuss these four and multiple views for the same source obj.
SortDescriptions prop. is a collection of SortDescription which chooses a field and order, sort by datetime, then by
name. a clear method to return to unsorted. eg. three buttons to sort and toggle.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
157
158
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
There is no explicit relationship with ListBox. if additional controls bound, they would sort with it. Now a
GroupDescriptions prop. containing PropertyGroupDescription obj. but it has no eect without the GroupStyle prop.
set with a HeaderTemplate.
1
2
3
4
5
6
7
8
>
159
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
160
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
Path =/}"
Path =/ DateTime }"
Path = Photos /}"
Path = Photos / DateTime }"
161
82
83
84
85
86
87
88
89
90
91
92
93
sorting is applied before grouping. first sorting criteria should be same as grouping otherwise output doesnt make
much sense. can pass null to get total custom control in the value converter.
Filtering gives a property Filter of type PredicateObject. its null by default e.g. show only photos from last 7
days.
navigation means managing the current item, not the other kind of nav. ICollectionView has CurrentItem CurrentPosition and also methods for changing them. e.g. prev/next photo buttons are handled like this view initializes
to 0 and first item listbox initializes to -1 and null (unselected).
prop. paths in Bindings are useful for master/detail interfaces. sorting, grouping, filtering automatic. but navigation only when IsSynchronizedWithCurrentItem=true. otherwise SelectedItem and CurrentItem are separate.
CollectionViewSource can be used to create new views and applied to targets. CollectionViewSource has its own
SortDescriptions and GroupDescriptions properties and a Filter event to be used from xaml. must include another
162
namespace. IsSynchronizedWithCurrentItem=true by default for custom views. have to explicitly set false. kind of a
bit inconsistent. but we acknowledging view existance by custom view.
Lets discuss data providers. source obj can be arbitrary. you could bind to db, registry, excel spreadsheet etc.
with enough code. an obj. that exposes right props and notifications and handles messy details work involved
might overweight benefits if writing all logic yourself two generic data-binding-friendly way to expose common items.
XmlDataProvider and ObjectDataProvider. starting with wpf 3.5 sp1 data binding works with LINQ (language
independent query) you can set Source or DataContext to a LINQ and the enumerable result is used. Now with LINQ
to SQL and LINQ to XML, is an easy way than using wpf data providers.
We use xData to avoid compiler errors. namespace pollution avoided with xmlns=. Bindings XPath prop used
rather than Path. if external file, even easier. GameStat/@Type would fill list with each GameStats Type attribute.
data provided in XmlNode etc. objects from System.Xml so you can use Path and XPath together. needs hierarchical
data template if you want to bind to xml tree.
1
2
3
< XmlDataProvider x : Key =" dataProvider " XPath =" GameStats " Source =" GameStats . xml "/ >
< Label Content ="{ Binding Source ={ StaticResource dataProvider } ,
XPath = GameStat / HighScore , Path = OuterXml }"/ >
Chapter 31
Lecture 31
In the last lecture, we discussed the view between binding source and target sorting, grouping, filtering, navigating.
creating additional views, data providers (xml and object), used xml data provider to fill a listbox, now use hierarchical
data template.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml "
Title =" XML Data Binding " >
< Window . Resources >
< H ie r a r c h i c a l D a t a T e m p l a t e DataType =" GameStats "
ItemsSource ="{ Binding XPath =*}" >
< TextBlock FontStyle =" Italic "
Text =" All Game Stats "/ >
</ HierarchicalDataTemplate >
< H ie r a r c h i c a l D a t a T e m p l a t e DataType =" GameStat "
ItemsSource ="{ Binding XPath =*}" >
< TextBlock FontWeight =" Bold " FontSize ="20"
Text ="{ Binding XPath = @Type }"/ >
</ HierarchicalDataTemplate >
< DataTemplate DataType =" HighScore " >
< TextBlock Foreground =" Blue " Text ="{ Binding XPath =.}"/ >
</ DataTemplate >
< XmlDataProvider x : Key =" dataProvider " XPath =" GameStats " >
<x : XData >
< GameStats xmlns ="" >
<! - - One stat per game type -->
< GameStat Type =" Beginner " >
< HighScore >1203 </ HighScore >
</ GameStat >
< GameStat Type =" Intermediate " >
< HighScore >1089 </ HighScore >
</ GameStat >
< GameStat Type =" Advanced " >
< HighScore >541 </ HighScore >
</ GameStat >
</ GameStats >
</ x : XData >
</ XmlDataProvider >
</ Window . Resources >
< Grid >
< TreeView
ItemsSource ="{ Binding Source ={ StaticResource dataProvider } ,
XPath =.}" / >
</ Grid >
163
164
40
hierarchicaldatatemplate for every node and datatemplate for a leaf node. hierarchicaldatatmplate allow specifying
children using ItemSource prop. =all children. datatype means eect all instances within the scope. datatype
corresponds to xmlnode name. no key. internally datatype value used as key.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
< rss version ="2.0" xmlns : atom =" http :// www . w3 . org /2005/ Atom "
xmlns : georss =" http :// www . georss . org / georss " >
</ rss >
< XmlDataProvider Source =" http :// twitter . com / statuses / user_timeline /24326956. rss "
X m lN a m es p ac e M an a ger ="{ StaticResource namespaceMapping }"
XPath =" rss / channel " x : Key =" dataProvider "/ >
Now lets discuss ObjectDataProvider. .net object as a data source. so what does that add against binding directly
to a .net obj. Declaratively instantiate the source object with a parameterized constructor. Bind to a method on
the source object. Have more options for asynchronous data binding. When binding not quick, async so UI doesnt
stuck. wpf has two ways to mark async. IsAsync prop of Binding, XmlDataProvider and ObjectDataProvider have an
IsAsynchronous prop. false by default on objDP, true by default for XmlDP. create source obj on background thread.
when IsAsync ture (false by default), source prop invoked on background thread property getters supposed to be fast
so shouldnt need.
first example wraps photos. its the same, even binding path because binding unwraps. it can also create the
object given its type.
1
2
3
4
5
6
7
8
9
binding to a method is useful for classes that are not designed for data binding. imagine photos class had GetFolderName method. can use MethodParameters. if Path used. it would apply to the obj returned.
1
< O bj ec tD at aP ro vi der x : Key =" dataProvider " ObjectType ="{ x : Type local : Photos }" >
165
2
3
4
5
1
2
3
Binding.Mode can be OneWay i.e. The target is updated whenever the source changes. TwoWay i.e. A change
to either the target or source updates the other. OneWayToSource. This is the opposite of OneWay. The source is
updated whenever the target changes. OneTime. This works just like OneWay, except changes to the source are not
reflected at the target. The target retains a snapshot of the source at the time the Binding is initiated.
useful for editable datagrid and textbox (by default) thats why convertback method. only convertback on onewaytosource.
UpdateSourceTrigger. Do you want the two way source to be updated on every key stroke. PropertyChanged.
changed when target prop value changes. LostFocus. changed when focus lost. Explicit. call BindingExpression.UpdateSource which you can get from any frameworkelement.getbindingexpression
We can also have validation rules. want to validate as soon as possible for user feedback. without binding you
could insert custom logic but now the data is auto-pushed to target. lets say we want valid .jpg file. 2 ways. validation
rule or use source exceptions. Binding has ValidationRules prop that can be set to one or more ValidationRule derived
objects.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
validation check whenever attempt to update target. in this case on LostFocus because it is default. when invalid,
an error adorner rendered on top of element. by default thin red border but can use Validation.ErrorTemplate attached
prop on target element to customize it, also other properties for custom control.
1
2
3
4
5
6
7
8
9
166
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/>
but what if already exceptions thrown by target. also the source can implement System.ComponentModel.IDataErrorInfo.
easier way in wpf 3.5 sp1.
Lets write an RSS reader without code. a two-way textbox so that user can change feed address. bindsdirectlytosource so path does not refer to the rss feed. UpdateSourceTrigger of PropertyChanged so update with every
keystroke. listbox/frame share the source. master detail.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
< Window xmlns =" http :// schemas . microsoft . com / winfx /2006/ xaml / presentation "
xmlns : x =" http :// schemas . microsoft . com / winfx /2006/ xaml " Title =" RSS Reader " >
< Window . Resources >
< XmlDataProvider x : Key =" Feed "
Source =" http :// twitter . com / statuses / user_timeline /24326956. rss "/ >
</ Window . Resources >
< DockPanel
DataContext ="{ Binding Source ={ StaticResource Feed } ,
XPath =/ rss / channel / item }" >
< TextBox DockPanel . Dock =" Top "
Text ="{ Binding Source ={ StaticResource Feed } ,
B i n d s D i r ectl yToS ource = true , Path = Source ,
U pd a t eS o urceTrigger = PropertyChanged }"/ >
< Label DockPanel . Dock =" Top "
Content ="{ Binding XPath =/ rss / channel / title }"
FontSize ="14" FontWeight =" Bold "/ >
< Label DockPanel . Dock =" Top "
Content ="{ Binding XPath =/ rss / channel / description }"/ >
< ListBox DockPanel . Dock =" Left " DisplayMemberPath =" title "
ItemsSource ="{ Binding }"
I s S y n c h r o n i z e d W i t h C u r r e n t I t e m =" True " Width ="300"/ >
< Frame Source ="{ Binding XPath = link }"/ >
</ DockPanel >
</ Window >
167
168
Chapter 32
Lecture 32
Concurrency is More than one thing happening at the same time. comparison with events. why still concurrency.
responsive user interface. simultaneous requests. parallel programming.
Thread: execution path that can proceed independently of others. normal processes (programs in exec.) have one
thread. multithreaded programs have more and can share data. lets create one.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class ThreadTest
{
static void Main ()
{
Thread t = new Thread ( WriteY );
t . Start ();
for ( int i = 0; i < 1000; i ++) Console . Write (" x ");
}
static void WriteY ()
{
for ( int i = 0; i < 1000; i ++) Console . Write (" y ");
}
}
Typical Output :
Xxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxx
interleaved because of time slicing. real parallel on multicore but still repeated blocks cuz of the way Console
handles it. a thread is pre-empted because of time slicing. a threads IsAlive=true once starts and until ends. Name
property, Thread.CurrentThread is the currently executing thread.
Join and Sleep. a thread is blocked when waiting. can use ThreadState property.
1
2
3
4
5
169
170
6
7
8
9
10
11
171
Lets discuss thread safety. In this code, we can output Done twice. and the odds increase if statements are reversed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class ThreadSafe
{
static bool _done ;
static readonly object _locker = new object ();
static void Main ()
{
new Thread ( Go ). Start ();
Go ();
}
static void Go ()
{
lock ( _locker )
{
if (! _done ) { Console . WriteLine (" Done "); _done = true ; }
}
}
}
Passing Data to Threads. use lambda expression (easiest) or use object param.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
172
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
There are IsBackground and Priority properties. signaling between threads using a ManualResetEvent (simplest).
WaitOne and Set. ReSet closes the signal.
1
2
3
4
5
6
7
8
9
10
Chapter 33
Lecture 33
long running operations make application unresponsive. because main thread used for rendering UI and responding
to events. start up worker thread and update UI when finished. but UI updation usually possible only on UI thread.
so, forward the request to UI thread.(or marshal it). Low level way is to call BeginInvoke or Invoke on the elements
Dispatcher object. it takes a delegate and queues it on the UI thread. Invoke does same but then blocks until it is
done. so you can return a value. but if you dont need BeginInvoke is better.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
173
174
18
19
ThreadPool save time of thread creation. cant name thread and difficult debugging. always background. blocking
can degrade performance. Thread.CurrentThread.IsThreadPoolThread property. threadpool creates or reduces real
threads using a hillclimbing algo to maximize cpu usage and reduce slicing.
1
2
3
ThreadPool . QueueU serWor kItem ( notUsed = > Console . WriteLine (" Hello "));
Task . Run (() = > Console . WriteLine (" Hello from the thread pool "));
Lets discuss Tasks. no easy way to get return value from a thread. we can join and use shared data. exceptions
difficult too. cant tell to start something else when finished. task: a higher level abstraction. tasks can be chained
using continuations. can use threadpool. with TaskCompletionSource callback approach.
starting a task is like creating a thread. except started right away (hot) and in a thread pool. task.wait is like
Join. Task has generic subclass TaskTReturn. task.Result blocks.
1
2
3
4
5
6
7
8
9
10
11
12
13
Continuations says when finished continue with something else. two ways.
1
2
3
4
5
6
7
8
9
10
11
12
175
13
14
15
calling any function signals the task. call exactly once. following example prints 42 after 5s. calling this is equivalent
to creating long running task. lets do the same without a thread. then attaching continuation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
176
8
9
10
11
12
13
14
15
16
17
Chapter 34
Lecture 34
In last lecture we discussed Threadpool to avoid thread creation time. Task concept one thread many tasks. Continuations / Exceptions / Returns. Task Completion Source. discussed Task.Delay.
Synchronous vs. asynchronous. async typically return quickly. called non-blocking. thread.start, task.run, attaching continuations. for io bound we can usually work without thread. for cpu bound we can start and return
task.
cpu bound async tasks.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
177
178
11
12
13
14
15
Task D i s pl ay P r i m e C o u n t s A s y n c ()
{
var machine = new PrimesStateMa ch in e ();
machine . Dis pl ay Pri me Co unt sF ro m (0);
return machine . Task ;
}
class Prim es St at eM ac hin e
{
T a s k C o m p l e t i o n S o u r c e < object > _tcs = new TaskCompletionSource < object >();
public Task Task { get { return _tcs . Task ; } }
public void D i s p l a y P r i m e C o u n t s F r o m ( int i )
{
var awaiter = GetPrimesCo u n tA s y nc ( i *1000000+2 , 1000000). GetAwaiter ();
awaiter . OnCompleted (() = >
{
Console . WriteLine ( awaiter . GetResult ());
if ( i ++ < 10) D is pl ay P r i m e C o u n t s F r o m ( i );
else { Console . WriteLine (" Done "); _tcs . SetResult ( null ); }
});
}
}
C# 5.0 introduces async and await keywords. eliminates plumbing for async code. as simple as sync code. await
simplifies attaching continuations. e.g. also code to handle if sync completion. and some other details.
1
2
179
3
4
5
6
7
8
returning to example. we can call it with await and use async keyword so compiler treats await specially. async
can be applied to methods returning void or Task or TaskTResult.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
async doesnt change method so no need to list in interface. can add async when implementing. methods with
async are called asynchronous. when await. method returns to caller. but before returning a continuation attached to
the task. if exception rethrown, otherwise return value assigned to await statement.
lets see the expansion again. await expression returns int because Taskint also possible to wait on void Task.
1
2
3
4
5
6
7
8
9
10
11
capturing local state in await. real power of await. when execution resumes in continuation, local vars have the
same values compiler translates into state machines. a general method. if we do ourself we may be doing the complex
code we showed before. if sync context, same thread e.g. UI. otherwise whatever free thread lets write a UI program
that remains responsive with a cpu bound task. lets start with the sync version.
1
2
3
4
5
180
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
asynchronous version. simplicity. call async functions. and await them. Go leases time on UI thread. Task.Run is
the real parallel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
simple but have to handle re-entrancy. and real parallel code does not use shared state. another example. download
web pages and sum their lengths. System.Net.WebClient.DownloadDataTaskAsync method. returns Taskbyte[] so
await returns byte[].
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
async void Go ()
{
_button . IsEnabled = false ;
string [] urls = " www . albahari . com www . oreilly . com www . linqpad . net ". Split ();
int totalLength = 0;
try
{
foreach ( string url in urls )
{
var uri = new Uri (" http ://" + url );
byte [] data = await new WebClient (). Do wnloa dDat aTask Asyn c ( uri );
_results . Text += " Length of " + url + " is " + data . Length +
Environment . NewLine ;
totalLength += data . Length ;
}
_results . Text += " Total length : " + totalLength ;
}
catch ( WebException ex )
181
19
20
21
22
23
{
_results . Text += " Error : " + ex . Message ;
}
finally { _button . IsEnabled = true ; }
}
mirrors how we would write it sync. even though control returns to caller after first await, the finally blocks is not
run until method is logically completed. lets see underneath on the message loop.
1
2
3
4
5
6
7
event handler run via this loop. Go runs as far as await and then returns to this loop. compilers expansion of await
ensures a continuation is setup. because we awaited on a UI thread, the continuation is posted on the sync context,
which ensures it runs via message loop. Go keeps running pseudo-concurrently with UI thread. True concurrency
occurs while DownloadDataTaskAsync is running.
vs. course grained where the loop itself on worker thread. gets difficult when progress reporting.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
182
Chapter 35
Lecture 35
Lets revise the downloading code from last lecture.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
async void Go ()
{
_button . IsEnabled = false ;
string [] urls = " www . albahari . com www . oreilly . com www . linqpad . net ". Split ();
int totalLength = 0;
try
{
foreach ( string url in urls )
{
var uri = new Uri (" http ://" + url );
byte [] data = await new WebClient (). Do wnloa dDat aTask Asyn c ( uri );
_results . Text += " Length of " + url + " is " + data . Length +
Environment . NewLine ;
totalLength += data . Length ;
}
_results . Text += " Total length : " + totalLength ;
}
catch ( WebException ex )
{
_results . Text += " Error : " + ex . Message ;
}
finally { _button . IsEnabled = true ; }
}
we can return a Task from void function without explicitly return it. enables async call chains. compiler indirectly
uses TaskCompletionSource to implement methods returning Tasks. we can expand PrintAnswerToLife like this.
nuances aside.
1
2
3
4
5
6
7
8
9
10
11
whenever task finishes, execution returns to whoever awaited for the task. you can return TaskTResult if the
method returns TResult. internally that results in TCS signaled with a value.
183
184
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
async Task Go ()
{
await PrintA nswerT oLife ();
Console . WriteLine (" Done ");
}
async Task PrintA nswerT oLife ()
{
int answer =
await GetAnswerToLife ();
Console . WriteLine ( answer );
}
async Task <int > GetAnswerToLife ()
{
await Task . Delay (5000);
int answer = 21 * 2;
return answer ;
}
void Go ()
{
Prin tAnswerToLife ();
Console . WriteLine (" Done ");
}
void PrintAnsw erToLi fe ()
{
int answer = GetAnswerToLife ();
Console . WriteLine ( answer );
}
int GetAnswerToLife ()
{
Thread . Sleep (5000);
int answer = 21 * 2;
return answer ;
185
33
same ease of programming as sync. intentional. so three steps. write sync. use async and await. return Task and
TaskTResult so awaitable. This means only Task.Run for real parallel cpu task and TCS for real parallel IO task.
rest of TCS are taken care of by compiler.
async call graph exec. brief sync exec on thread calling Go. everyone await and returns. when Delay fires a thread.
remaining statements run. eventually Gos task is marked completed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
async Task Go ()
{
var task = PrintAnswerToLife ();
await task ;
Console . WriteLine (" Done ");
}
async Task PrintA nswerT oLife ()
{
var task = GetAnswerToLife ();
int answer = await task ;
Console . WriteLine ( answer );
}
async Task <int > GetAnswerToLife ()
{
var task = Task . Delay (5000);
await task ;
int answer = 21 * 2;
return answer ;
}
Lets discuss Parallelism. Go is not awaited, allowed and required here. so lets see how to run two tasks in parallel
and then await them. true concurrency at bottom level operations. if a sync context, only pseudo-concurrency. so
only switched on await. that means we can increment shared var without locking. but cant assume same value before
and after await.
1
2
3
4
5
6
7
8
9
10
11
12
186
14
15
16
17
18
19
20
21
22
23
24
25
26
27
can even use cancellation with Task.Wait. i.e. sync methods but have to call cancel from another task. infact you
can give a time interval after which auto cancelled. useful for timeouts.
Progress reporting. thread safety issues. iprogress and progress. progress ctor.
1
2
3
4
187
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Task < int > winningTask = await Task . WhenAny ( Delay1 () , Delay2 () , Delay3 ());
Console . WriteLine (" Done ");
Console . WriteLine ( winningTask . Result );
int answer = await await Task . WhenAny ( Delay1 () , Delay2 () , Delay3 ());
Task < string > task = SomeAsyncFunc ();
Task winner = await ( Task . WhenAny ( someOperation , Task . Delay (5000)));
if ( winner != task ) throw new TimeoutException ();
string result = await task ;
188
Chapter 36
Lecture 36
we can implement timeout with whenany task combinator. on the other hand WhenAll waits for all. dierence is that
should task1 fault, we never get to.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int answer = await await Task . WhenAny ( Delay1 () , Delay2 () , Delay3 ());
Task < string > task = SomeAsyncFunc ();
Task winner = await ( Task . WhenAny ( someOperation , Task . Delay (5000)));
if ( winner != task ) throw new TimeoutException ();
string result = await task ;
await Task . WhenAll ( Delay1 () , Delay2 () , Delay3 ());
Task task1 = Delay1 () , task2 = Delay2 () , task3 = Delay3 ();
await task1 ; await task2 ; await task3 ;
Task task1 = Task . Run (() = > { throw null ; } );
Task task2 = Task . Run (() = > { throw null ; } );
Task all = Task . WhenAll ( task1 , task2 );
try { await all ; }
catch
{
Console . WriteLine ( all . Exception . InnerExceptions . Count );
}
Task <int > task1 = Task . Run (() = > 1);
Task <int > task2 = Task . Run (() = > 2);
int [] results = await Task . WhenAll ( task1 , task2 );
async Task < int > GetTotalSize ( string [] uris )
{
IEnumerable < Task < byte [] > > downloadTasks = uris . Select ( uri = >
new ( WebClient ). D ownl oadDa t a T a s k A s y n c ( uri ));
byte [][] contents = await Task . WhenAll ( downloadTasks );
return contents . Sum ( c = > c . Length );
}
async Task < int > GetTotalSize ( string [] uris )
{
IEnumerable < Task < int > > downloadTasks = uris . Select ( async uri = >
( await new WebClient (). D own loadD ataT askAs ync ( uri )). Length );
int [] contentLengths = await Task . WhenAll ( downloadTasks );
return contentLengths . Sum ();
}
189
190
Task Parallel Library exploit multicore for real parallel tasks. 3 steps partition into small chunks, process, collate
the results in thread-safe manner. lock contention and lot of cumbersome code. data parallelism vs. task parallelism.
data parallelism easier and scales well. it also structured. same place in code where parallelism starts and ends.
concurrent collections also useful when you want a thread-safe collection three static methods in the Parallel class
Parallel.Invoke is not a shortcut for creating many threads. actually batches to use processors efficiently. combining
on the user. following is thread-unsafe. locking may make slow. concurrentBag.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
191
Next we discuss using loop counter, breaking out of loops, and using per-thread counters. loop counters are easy
with sequential. use overloaded version. what is parallel loop state.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int i = 0;
foreach ( char c in " Hello , world ")
Console . WriteLine ( c . ToString () + i ++);
public static P ar al le lL oo pR es ult ForEach < TSource > (
IEnumerable < TSource > source ,
Action < TSource , ParallelLoopState , long > body )
Parallel . ForEach (" Hello , world " , (c , state , i ) = >
{ Console . WriteLine ( c . ToString () + i ); });
public class Par allelL oopSta te
{
public void Break ();
public void Stop ();
public bool IsExceptional { get ; }
public bool IsStopped { get ; }
public long ? L o w e s t B r e a k I t e r at i o n { get ; }
public bool S h o u l d E x i t C u r r e n t I t e r a t i o n { get ; }
}
a normal break in parallel. di between Break and Stop. Break reaches atleast the sequential point. what about
local value. use overload.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// OUTPUT : Hello
problem above. locking slows down. what if every thread took lock once. possible with summation.
192
1
2
3
4
5
6
7
8
9
Concurrent collections include concurrent stack, concurrent queue, concurrent bag, concurrent dictionary. They
are optimized for concurrent. but also useful for thread-safe. conventional outperform in all but highly concurrent
situations. thread-safe collection doesnt guarantee thread safe code. you enumerate, another modifies, you get combination of old and new. no concurrent version of List. stack queue bag implemented with linked list but less mem
efficient as a consequence. e.g. the following code is 3 times slower but not with reads. also some atomic test and act.
like TryPop.
IProducerConsumerCollectionT has no need to lock. adds TryAdd and TryTake methods. with stack, most
recent, queue oldest, and bag whatever. concurrentbag is an unordered collection. its kind of linked list for each
thread. add has almost no contention.
BlockingCollectionT wait instead of returning false. wrapper class. also lets you limit the size. called bounded
blocking collection. ctor takes a iproducerconsumer and limit. default is to make a queue. can also give multiple
collecitons and use AddtoAny TakefromAny. can also take GetConsumingEnumerable. Lets make a producer consumer
queue.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
193
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
194
Chapter 37
Lecture 37
In the last lecture, finished discussion on tasks and multithreading. important part of event driven and visual programming. to remain responsive. the task parallel library. Parallel.Invoke, For, Foreach. loop counter, break, stop,
per-thread counter. concurrent collections, stack, queue, bag, dictionary. ended with a producer consumer queue with
tasks.
Now well discuss event driven programming on the web and mobile. client side programming and event-handling.
server side web programming in other courses.
static web sites were there initially. html. hypertext markup language. display information and thats it. today
websites reach interactivity of desktop applications. because of JavaScript. animation, interactivity, dynamic visual
eects. e.g. immediately give error msg when wrong data, give total when add to shopping cart, slideshow instead of
image list, expand collapse information, popup tooltips. immediate feedback. no delay like server side. no constant
loading reloading. so feels like desktop programs.
e.g. you visited google maps. JS (javascript) in action. zoom in zoom out. prev. map sites used reloading.
Javascript was introduced in 95 by netscape. about as old as web. but mostly hobby things like flies with
mouse or messages that move like stock ticker. many scripts but didnt work in all browsers, even crashed them
often. JS has nothing to do with Java, originally named LiveScript but renamed to associate with the then hot Java.
initial interoperability problems in netscape and IE. often added incompatible features. MS introduced jScript. their
version of JS for IE. these days mostly handled. standardization. some quirks left. called ECMAScript. the official
standardization name. refueled by high profile sites like google using JS in last decade. now JS even used by some
non-web scripting. even flash ActionScript based on it. or write widgets, phone apps etc.
JS is a prog language. can be hard for some. also browser incompatibilities make testing difficult. jQuery is a JS
library intended to make JS programming easier. jQuery solves JS complexity and browser incompatibilities. can do
things in single LOC that would take hundreds. many advanced features come as jQuery plugins. used on millions of
websites.
HTML: structural layer and CSS: presentation layer and JS: behavioral layer.
HTML has simple commands called tags. doctype is of html5 here. tells browser how to render the page. what
standards. five types of html in use: HTML 4.01 Transitional, HTML 4.01 Strict, XHTML 1.0 Transitional, XHTML
1.0 Strict, and HTML5. all current browsers understand them all. starting and closing tags like XML. at least three
tags. html root tag, head tag containing title etc, and body tag containing all parts to be rendered in browser window.
p/p is paragraph strong/strong is emphasis a href=http:.../a is a hyperlink. XML attribute and value.
validating html means checking if all tags appropriately closed etc.
1
2
3
4
5
6
7
8
9
10
195
196
originally there was only HTML. CSS is a formatting language. html only to structure, so h1 h2 are both
headings with di imp ul is an unordered list. CSS adds design. CSS style is a rule telling web browser how to
display an element. e.g. you can make CSS rule to make all h1 tags 36 px tall, in courier font, and in orange. CSS
can do more powerful stu, like add border, change margins, and even control exact placement on web page. JS can
add/remove/change CSS properties based on input or mouse clicks. even animate from one property to another. like
yellow to red. or animate across screen by changing position.
a single CSS style is a rule that tells how to format. make this look like that. selector and declaration block.
e.g. selector can be headline, paragraph of text, photo etc. declaration block can turn text blue, add red border around
a paragraph, position the photo at center of page etc. e.g. p color: red; font-size: 1.5em; selector, declaration block
has declarations. each is a property value pair and then ;.
JS lets a page re-act. smart web forms. lets user know when they miss important info, make elements appear or
disappear, or move around a webpage. even load new content from web server without reloading. more engaging and
eective web sites.
Client side vs. server side. prog lang for the web browser. alternate is a server prog lang. php, .net, asp, cold fusion,
ruby on rails, etc. they run on web server. log of intelligence by accessing DB, process CC, send emails. visitors wait
until response comes. client side lang can re-act immediately. responsive. other client side technologies are applets,
silverlight, flash. often requires a plugin or start slow because of downloading. sometimes even di to see if flash or
JS. once yahoo maps was flash. then re-written. right click and see if About the Flash Player Ajax brings client-side
server-side together. JS talks to server, downloads content, and update webpage. google maps lets you move to new
areas. JS is a prog lang and can be used on server side. e.g. Node.js supports JS on server-side.
compiled vs scripted languages (interpreted). JS interpreter is in web browser. lets write a prog to ask visitor
name, get response, and print a welcome msg. web browser has layout or rendering engine (understanding HTML and
CSS) and a JS interpreter. tell web browser about JS in a script/script tag. Here is a script in html 4.01 and in
html5.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<! DOCTYPE HTML PUBLIC " -// W3C // DTD HTML 4.01// EN " " http :// www . w3 . org / TR / html4 / strict . dtd " >
< html >
< head >
< title > My Web Page </ title >
< script type =" text / javascript " >
</ script >
</ head >
usually in head section and at one place. but its ok to put it anywhere and in multiple tags. script can also be
placed after /body so script loaded after page displayed can also use external script files. easy to share. separate
tags if you want inline code AND src attrib for external file. can and often use multiple external files.
1
2
3
4
5
6
7
8
197
9
10
11
12
13
14
15
16
17
18
19
20
1
2
3
4
< book = javascript \& jquery the Missing Manual page 30 >
< script >
document . write ( <p > Hello world ! </p > );
</ script >
before the web page because of placement. web page appears after OK pressed. use document.write and script
tag anywhere.
1
2
3
4
< link href ="../ _css / site . css " rel =" stylesheet " >
< script src ="../ _js / jquery -1.6.3. min . js " > </ script >
< script >
$ ( function () {
198
5
6
7
lot of basic syntax like C++, C#. create a variable using var x, names begin with letter, $, or . var days =
[Mon, Tues, Wed, Thurs, Fri, Sat, Sun]; alert(days[0]); var playList = []; var prefs = [1, 223, www.oreilly.com,
false]; prefs.push(test); prefs.push(test,test2); arrays grow prefs.unshift(test); prefs.unshift(test,test2); insert at
start shift() gets/removes the first element. queue using push/shift pop() removes last. stack alert and prompt
functions.
1
2
3
4
5
6
7
8
9
if, while, for, dowhile like C#. function declarations. no types. return value.
Lets discuss jQuery now. many JS programs select elements, add new content, hide and show content, modify tags
attributes, determine value of form fields, and react to user actions. the details complicated specially with browser
interoperability. libraries oer a set of functions to make these tasks easy.
only 30k compressed library size. easy to learn. used on millions of sites. free. dev community. plugins !!!
where to get jQuery.js. Use CDNs dont need to host your own. often cached. google one is v popular.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
< script src =" http :// ajax . aspnetcdn . com / ajax / jQuery / jquery -1.6.3. min . js " >
</ script >
< script src =" http :// code . jquery . com / jquery -1.6.3. min . js " > </ script >
< script src =" http :// ajax . googleapis . com / ajax / libs / jquery /1.6.3/ jquery . min . js " >
</ script >
< script src =" js / jquery -1.6.3. min . js " > </ script >
< script >
\ $ ( document ). ready ( function () {
// your programming goes here
});
</ script >
\ $ ( function () {
// your programming goes here
}); // end ready
second script tag for jQuery prog. $(document).ready() waits until HTML of webpage loads and then runs the
function. browser processes in order and to work with elements you want them downloaded. shortcut for ready
function.
199
dynamically changing webpage is key idea. mouse over, click, detail info. e.g. date picker is run by JS but itself is
made of HTML / CSS. JS just makes presentation interactive.
two steps. select sth, do sth with it. do sth can be change prop, add/remove element, extra info, add/remove class
attrib, or a combination of these.
200
Chapter 38
Lecture 38
HTML DOM is much like an XML DOM. JS provides ways to select e.g. some browsers allow selecting by CSS
sometimes not cross browser.
1
2
3
to select a tags with class navButton, you have to select all a tags, then iterate and find the ones with the
right class. in jQuery $(selector) e.g. $(#banner) is the tag with id banner. $(#banner).html(h1JavaScript was
here/h1);. html is a jQuery helper function.
Basic selectors are ID selectors, element selectors, class selectors.
1
2
3
4
5
6
7
8
9
10
11
$ ( . submenu )
$ ( . submenu ). hide ();
Advanced selectors are descendent selectors $(#navBar a) , child selectors $(body p) , adjacent sibling
$(h2 + div) , attribute selectors $(img[alt]), $(input[type=text]), $(a[href=mailto:]),
$(a[href$=.pdf]),
$(a[href*=missingmanuals.com]) , form element selectors later. jQuery filters are :even :odd $(.striped tr:even)
:first :last :not $(a:not(.navButton)); :has $(li:has(a)) di from descendent :contains $(a:contains(Click Me!))
:hidden :visible $(div:hidden).show();
201
202
jQuery selection. dont end up with DOM lists. rather jQuery equivalents automatic loops. $(#slideshow
img).hide(); chaining functions... $(#popUp).width(300).height(300); $(#popUp).width(300).height(300).text(Hi!).fadeIn(100
lets see jQuery functions to add content
take this example .html() can read and change alert($(#errors).html()); will show h2Errors:/h2. $(#errors).html(pThere are four errors in this form/p);. .text() wont replace tags. $(#errors h2).text(No errors
found); encodes html tags to .text() so p would become <p> .append()... .prepend() $(#errors).append(pThere
are four errors in this form/p); .before() .after() input type=text name=userName id=userName $(#userName).after(span class=errorUser name required/span); input type=text name=userName id=userNamespan
class=errorUser name required/span .remove() $(#popup).remove(); .replaceWith() $(#product101).replaceWith(pAdde
to cart/p);.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Attributes can be manipulated with addClass removeClass toggleClass. and css. var bgColor = $(#main).css(backgroundcolor); $(body).css(font-size, 200$(p.highlight).css(border, 1px solid black); multiple css props can be changed
together.
1
2
3
4
5
6
7
8
9
\ $ ( \# highlightedDiv ). css ({
background - color : \# FF0000 ,
border : 2 px solid # FE0037
});
for changing html attribute, css and addClass are just shortcuts general purpose attr() and removeAttr() var imageFile = $(#banner img).attr(src); $(#banner img).attr(src,images/newImage.png); $(body).removeAttr(bgColor);.
acting on each element in a selection. when you do want something special. each() and anonymous function. use
this for current element as DOM obj. $(this) for current element as jQuery selection.
1
2
3
4
5
203
6
7
8
9
10
11
12
13
events. things happen to webpage. page loading, mouse move, key press you respond to events. mouse events: click,
dblclick, mousedown, mouseup, mouseover, mouseout, mousemove. doc/window events: load, resize, scroll, unload.
form events: submit, reset, change, focus, blur. keyboard: keypress (over n over), keydown, keyup.
step 1: select elements, step 2: assign an event, step 3: pass function to event.
1
2
3
\ $ ( function () {
// do something on document ready
});
jquery events. hover. toggle is like hover except worked on and o by clicks. event object is passed to all functions
handling events.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
204
Chapter 39
Lecture 39
Event properties. String.fromCharCode(evt.which) evt.preventDefault(); or return false; to stop normal behavior
e.g. links, form submit etc. remove events $(.tabButton).unbind(click); default event bubbling and can stop it
evt.stopPropagation(); generic way to bind events (click, mouseover etc. special) $(#selector).bind(click, myData,
functionName); $(selector).bind(click, functionName); equivalent is $(selector).click(functionName);
can bind multiple events
1
2
3
4
5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
205
206
15
16
17
18
19
20
21
22
23
24
25
\ $ ( \# theElement ). bind ({
click : function () {
// do something interesting
} , // end click function
mouseover : function () {
// do something interesting
}; // end mouseover function
}); // end bind
FAQ example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
< script src ="../ _js / jquery -1.6.3. min . js " > </ script >
< script >
\ $ ( document ). ready ( function () {
\ $ ( . answer ). hide ();
\ $ ( \# main h2 ). toggle (
function () {
\ $ ( this ). next ( . answer ). fadeIn ();
\ $ ( this ). addClass ( close );
},
function () {
\ $ ( this ). next ( . answer ). fadeOut ();
\ $ ( this ). removeClass ( close );
}
); // end toggle
});
</ script >
jQuery animations. $(element).fadeOut(slow);. fast normal slow or number of ms . default 200 400 600. fadeIn,
fadeOut, fadeToggle. slideDown, slideUp, slideToggle.
207
generic animate. any numeric css prop. border-left-width becomes borderLeftWidth cuz JS doesnt understand
hyphen even += -=.
1
2
3
4
5
6
7
8
9
10
\ $ ( \# message ). animate (
{
left : 650 px ,
opacity : .5 ,
fontSize : 24 px
},
1500
);
208
11
12
13
14
15
16
17
easing. linear or swing $(#element).slideUp(1000,linear); can event pass a function to run when the animation
finishes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
forms.
1
2
3
4
5
6
7
8
9
< input name =" quantity " type =" text " id =" quantity " >
< input name =" total " type =" text " id =" total " >
var unitCost = 9.95;
var amount = \ $ ( \# quantity ). val ();
var total = amount * unitCost ;
total = total . toFixed (2);
\ $ ( \# total ). val ( total );
209
submit event.
1
2
3
4
5
6
7
8
focus, blur, click, change (menus). react to choice from a list menu
cant do everything at client. page disappearing and reappearing. ajax lets webpage ask for info and update itself
when it comes. asynchronous JS and XML. term coined in 2005 for interactive sites coming from google. like google
maps, gmail.
210
Chapter 40
Lecture 40
In Last Lecture, we talk about event object and its properties. binding and unbinding events. jQuery animations,
easing, chaining. FAQ, login slider, photo gallery. forms and form selectors. now the real power. ajax.
what can be done. display NEW html content without reloading the page. submit form and instantly display
results. login without leaving the page. e.g. star rating widget. browsing through database info like you scroll down
on fb, twitter. nothing radical. except without loading a new page. can achieve same with HTML and server side
prog. ajax make pages feel more responsive and desktop like.
JS, server-side programming, and web browser, all work together. web browser: XMLHttpRequest object. makes
ajax possible. talks to web server and get response. JS: sends request, waits for response, process response, updates
web page. web server: receives request and responds as HTML, plain text, XML, JSON. or application server for more
complicated tasks. need web server for ajax examples.
For talking to web server, we create XMLHttpRequest (also called XHR in short) var newXHR = new XMLHttpRequest(); again browser incompatibilities call open to specify what kind of data and where it will go can GET
211
212
or POST newXHR.open(GET, shop.php?productID=34); write a callback function it will remove, add, change elements send data newXHR.send(null); GET newXHR.send(q=javascript); POST receive response callback invoked
and XHR receives status, text response, and possibly an XML response status = 200/304 all ok, 404 file not found,
500 internal server error, 403 access forbidden responseText has text of JSON or HTML, responseXML less commonly
used
the jQuery way. simplifies all steps except that of changing the webpage simplest is load function which loads HTML
into an area of web page e.g. load news in a div from a web-server $(#headlines).load(todays news.html); can only
load from same site... relative urls possible to add only a part $(#headlines).load(todays news.html #news);.
1
2
3
4
5
6
7
8
9
10
11
12
get() and post(). need server side to do anything else. server may not return html e.g. database records as xml or
json. jQuery handles dierences of GET and POST. no selector. stand by themselves.
1
2
3
formatting data. can send a product number, entire form, signup. format as query string of JS obj literal.
URL http://www.chia-vet.com/prod- ucts.php?prodID=18&sessID=1234. GET has limit. often thousands of chars.
$.get(rateMovie.php,rating=5); $.post(rateMovie.php,rating=5); $.post(rateMovie.php,rating=5&user=Bob);
favFood=Mac & Cheese // incorrect favFood=Mac%20%26%20Cheese // properly escaped var queryString = favFood= + encodeURIComponent(Mac & Cheese); $.post(foodChoice.php, queryString); better way is obj literal.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
name1 : value1 ,
name2 : value2
}
\ $ . post ( rankMovie . php , { rating : 5 });
var data = { rating : 5 };
\ $ . post ( rankMovie . php , data );
var data = {
rating : 5 ,
user : Bob
}
\ $ . post ( rankMovie . php , data );
var data = \ $ . post ( rankMovie . php ,
{
rating : 5 ,
user : Bob }
); // end post
213
processing data returned. call back first arg is data. servers often use XML of JSON. second arg is string about
status success. e.g. movie rating.
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
214
error handler.
1
2
3
4
5
6
7
8
9
JS format. method for exchanging data. JSON is JS so its quick n easy for JS. no XML like parsing. JSON is a
JS obj literal. (MUST use quotations if names have spaces etc.)
1
2
3
4
5
{
firstName : Frank ,
lastName : Smith ,
phone : 503 -555 -1212
}
215
6
7
8
9
10
11
{
firstName : Frank ,
lastName : Smith ,
phone : 503 -555 -1212
}
server returns a string formatted like a JSON obj literal. jQuery getJSON method. like get but data passed to
callback will be a JSON object.
1
2
3
4
5
6
var bday = {
person : Raoul ,
date : 10/27/1980
};
bday . person // Raoul
bday . date // 10/27/1980
var data = {
contact1 : {
firstName : Frank ,
lastName : Smith ,
phone : 503 -555 -1212
},
contact2 : {
firstName : Peggy ,
lastName : Jones ,
phone : 415 -555 -5235
}
};
data . contact1 . firstName
\ $ . each ( JSON , function ( name , value ) {
});
\ $ . getJSON ( contacts . php , limit =2 , processContacts );
216
Chapter 41
Lecture 41
Objective-C introduces smalltalk style messaging in C. early 1980s. used for NeXT computer. It is simple extension of
C. to create an object, send it an alloc message. NSMutableArray *arrayInstance = [NSMutableArray alloc];. initialize
it. [arrayInstance init];. can combine. nested message send. NSMutableArray *arrayInstance = [[NSMutableArray
alloc] init];. message = [receiver selector arguments]. e.g. add obj to array. [arrayInstance addObject:anotherObject];.
another message you can send to mutablearray. replaceObjectsInRange:withObjectsFromArray:range:. pairing of
labels and arguments a feature of objective-C. in other langs. arrayInstance.replaceObjectsInRangeWithObjectsFromArrayRange(a
anotherArray, anotherRange);. in objective-C. [arrayInstance replaceObjectsInRange:aRange withObjectsFromArray:anotherArray range:anotherRange];.
destroy using [arrayInstance release];. should also arrayInstance = nil;. otherwise dangling. but sending message
to nil is ok. nil is like null.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
NSString. [items addObject:@One]; @ is shortcut for creating NSString. NSString *myString = @Hello,
World!;. int len = [myString length];. len = [@Hello, World! length];. myString = [[NSString alloc] initWithString:@Hello, World!];. len = [myString length];.
NSLog. format string. int a = 1; float b = 2.5; char c = A; NSLog(@Integer: Integer: 1 Float: 2.5 Char: A
NSArray and NSMutableArray. also NSDictionary and NSSet. holds references. cannot hold primitives and C
structures. can call [array count]. int numberOfObjects = [array count]; [array insertObject:object atIndex:numberOfObjects];
cant add beyond end. exception. [array addObject:[NSNull null]]; // otherwise cannot hold nil. NSString *object =
[array objectAtIndex:0];
subclassing. root class of entire hierarchy. NSObject. objective-C keywords start with @. instance variables.
1
2
3
4
5
217
218
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
219
35
36
37
38
39
40
41
42
43
Getter setters can be made like above example. Lets see instance methods (and overriding).
1
2
3
4
5
6
7
8
9
10
- ( NSString *) description
{
NSString * descriptionString =
[[ NSString alloc ] initWithFormat : @ "\% @ (\% @ ): Worth \ $ \% d , recorded on \% @ " ,
possessionName ,
serialNumber ,
valueInDollars ,
dateCreated ];
return des cripti onStri ng ;
}
initializers start with init naming convention. id = any object. every object has isa pointer to class and thats how
methods are called. like vtable. self and super. other initializers.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
- ( id ) i n i t W i t h P o s s e s s i o n N a m e :( NSString *) name
valueInDollars :( int ) value
serialNumber :( NSString *) sNumber ;
- ( id ) i n i t W i t h P o s s e s s i o n N a m e :( NSString *) name
valueInDollars :( int ) value
serialNumber :( NSString *) sNumber
{
// Call the superclass s designated initializer
self = [ super init ];
// Did the superclass s designated initializer succeed ?
if ( self ){
// Give the instance variables initial values
[ self setPos sessio nName : name ];
[ self setSerialNumber : sNumber ];
[ self setVal ueInDo llars : value ];
dateCreated = [[ NSDate alloc ] init ];
}
// Return the address of the newly initialized object
return self ;
}
- ( id ) init
{
return [ self i n i t W i t h P o s s e s s i o n N a m e : @ " Possession "
valueInDollars :0
serialNumber : @ ""];
}
class methods
1
2
220
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
+ ( id ) randomPossession
{
// Create an array of three adjectives
NSArray * randomAdjectiveL ist = [ NSArray arrayWithObjects : @ " Fluffy " ,
@ " Rusty " ,
@ " Shiny " , nil ];
// Create an array of three nouns
NSArray * randomNounList = [ NSArray arrayWithObjects : @ " Bear " ,
@ " Spork " ,
@ " Mac " , nil ];
int adjectiveIndex = rand ()\% [ r an d o mA d j ec t i ve L i st count ];
int nounIndex = rand ()\% [ randomNounList count ];
NSString * randomName = [ NSString stringWithFormat : @ "\% @ \% @ " ,
[ randomAdjectiveList objectAtIndex : adjectiveIndex ] ,
[ randomNounList objectAtIndex : nounIndex ]];
int randomValue = rand ()\% 100;
NSString * randomSerialNumb er = [ NSString stringWithFormat : @ "\% c \% c \% c \% c \% c " ,
0 + rand ()\% 10 ,
A + rand ()\% 26 ,
0 + rand ()\% 10 ,
A + rand ()\% 26 ,
0 + rand ()\% 10];
// Once again , ignore the memory problems with this method
Possession * newPossession =
[[ self alloc ] i ni tW ith Po s s e s s i o n N a m e : randomName
valueInDollars : randomValue
serialNumber : r an domSerialNumber ];
return newPossession ;
}
obj-C is dynamically typed. NSMutableArray *items = [[NSMutableArray alloc] init]; [items doSomethingWeird];
2009-07-19 01:34:53.602 RandomPossessions[25326:10b]. *** -[NSCFArray doSomethingWeird]: unrecognized selector
sent to instance 0x104b40. objective-C has try-catch. usually for runtime errors that the programmer made better for
loop.
properties, simplified accessors.
1
2
3
4
5
6
7
8
9
10
11
221
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
- ( id ) i n i t W i t h P o s s e s s i o n N a m e :( NSString *) name ;
@property NSString * possessionName ;
@property NSString * serialNumber ;
@property int valueInDollars ;
@property NSDate * dateCreated ;
@end
@implementation Possession
@synthesize possessionName , serialNumber , valueInDollars , dateCreated ;
222
Chapter 42
Lecture 42
alloc and dealloc methods. manual reference counting. obj knows owner count retainCount. retain and release
methods. should you release a created object that is returned ?. Want to say dont release but i dont want to be the
owner. autorelease. added to NSAutoReleasePool. NSObject *x = [[[NSObject alloc] init] autorelease];.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- ( NSString *) description
{
return [ NSString stringWithFormat : @ "\% @ (\% @ ): Worth \ $ \% d , Recorded on \% @ " ,
possessionName ,
serialNumber ,
valueInDollars ,
dateCreated ];
223
224
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
- ( void ) dealloc
{
[ possessionName release ];
[ serialNumber release ];
[ dateCreated release ];
[ super dealloc ];
}
retain count rules. init, new, copy in name. assume you own. any other means. assume in autorelease. if you dont
own and want to make sure, call retain. no longer need and own than release or autorelease. when 0 count, dealloc
called.
225
similar to visual studio. the interface in xml. xib file. compiled to a nib file. ios application a directory containing
executables and resources. sounds familiar.
226
xib editing. select window to add controls. drag buttons. give them names.
227
mvc pattern. view objects. visible things. UIView subclasses. model objects. hold data and know nothing about
interface. often use standard containers. controllers keep things in sync.
228
IBOutlet, IBAction.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
setting connections. from the obj with pointer to the obj you want that pointer to point at. control-drag from
target to object. check connection in connection inspector.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
229
230
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@implementation QuizAppDelegate
- ( id ) init
{
// Call the init method implemented by the superclass
self = [ super init ];
if ( self ){
// Create two arrays and make the pointers point to them
questions = [[ NSMutableArray alloc ] init ];
answers = [[ NSMutableArray alloc ] init ];
// Add questions and answers to the arrays
[ questions addObject : @ " What is7 + 7?"];
[ answers addObject : @ "14"];
[ questions addObject : @ " What is the capital of Vermont ?"];
[ answers addObject : @ " Montpelier "];
[ questions addObject : @ " From what is cognac made ?"];
[ answers addObject : @ " Grapes "];
}
// Return the address of the new object
return self ;
}
231
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
}
// Get the string at that index in the questions array
NSString * question = [ questions objectAtIndex : c u r r e n t Q u e s t i o n I n d e x ];
// Log the string to the console
NSLog ( @ " displaying question : % @ " , question );
// Display the string in the question field
[ questionField setText : question ];
// Clear the answer field
[ answerField setText : @ "???"];
}
- ( IBAction ) showAnswer :( id ) sender
{
// What is the answer to the current question ?
NSString * answer = [ answers objectAtIndex : c u r r e n t Q u e s t i o n I n d e x ];
// Display it in the answer field
[ answerField setText : answer ];
}
232
Chapter 43
Lecture 43
In Last Lecture, we discussed objective C memory management rules, Wrote our first iPhone app: a quiz app, xib and
nib files and interface editor, MVC pattern, IBOutlet IBAction, Connection Inspector, then wrote init, showQuestion,
and showAnswer.
Core Location Framework. Lets make a whereami application. classes that enable finding geographical position.
distanceFilter and desiredAccuracy properties.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
233
234
1
2
3
4
5
6
7
8
9
10
11
Delegation is a design pattern. an OO approach to callbacks. allows callback methods to share data. a delegate
can only be sent messages specified in its protocol. for every object that can have a delegate, there is a corresponding
protocol.
1
2
3
4
5
6
7
8
9
10
11
12
13
235
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
236
protocols are like interfaces in other langs i.e. no implementation. protocols for delegations delegate protocols.
can be used to ask things from the delegate or inform of updates. can be @optional methods. by default required.
here all were optional. every object implements respondsToSelector: something like this (above). class has to declare
protocols it implements like other langs. no warning anymore.
memory and delegation. delegates are usually controllers. delegates never retained. retain cycle. assign attrib.
237
weak reference. lets display a map of current location.
Several instances of MKAnnotationView appear as icons on the MKMapView. An MKMapView displays the map
and the labels for the recorded locations. A UIActivityIndicatorView indicates that the device is working and not
stalled. A UITextField allows the user to input text to label the current location on the map.
drag the map view onto UIWindow.
1
2
3
4
5
6
7
8
9
10
11
12
13
@interface W h e re a mi A p pD e l eg a t e : NSObject
< UIApplicationDelegate , CLLocationManagerDelegate >
{
CLLocationManager * locationManager ;
IBOutlet MKMapView * worldView ;
IBOutlet U I Ac ti v it y In di c at o r V i e w * activ ityInd icator ;
IBOutlet UITextField * loc ati on Ti tl eF ie ld ;
}
@property ( nonatomic , retain ) IBOutlet UIWindow * window ;
@end
all we do is set showsUserLocation property of MKmapview and it will show users location.
1
2
3
4
5
6
7
8
9
10
11
238
12
13
14
15
16
17
18
19
20
21
too big the dot on world map. want to zoom in. when to send a zoom in message. instead MKMapView has
delegate.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
lets add an annotation. MKAnnotation protocol lets create a new MapPoint class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
239
17
18
}
@end
in xib file set text fields delegate to be the instance of WhereamiAppDelegate. this means we can implement
methods from UITextFieldDelegate.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@interface W h er e a mi A p pD e l eg a t e : NSObject
< UIApplicationDelegate , CLLocationManagerDelegate ,
MKMapViewDelegate , UITextFieldDelegate >
- ( BOOL ) t e x t F i e l d S h o u l d R e t u r n :( UITextField *) tf
{
// This method isn t implemented yet - but will be soon .
[ self findLocation ];
[ tf r e s i g n F i r st R e s p o n d e r ];
return YES ;
}
@interface W h e re a mi A p pD e l eg a t e : NSObject
< UIApplicationDelegate , CLLocationManagerDelegate ,
MKMapViewDelegate , UITextFieldDelegate >
{
CLLocationManager * locationManager ;
IBOutlet MKMapView * worldView ;
IBOutlet U I Ac ti v it y In di c at o r V i e w * activ ityInd icator ;
IBOutlet UITextField * loc ati on Ti tl eF ie ld ;
}
@property ( nonatomic , retain ) IBOutlet UIWindow * window ;
- ( void ) findLocation ;
- ( void ) foundLocation :( CLLocation *) loc ;
@end
240
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
Chapter 44
Lecture 44
Lets discuss touch events. touch events are hallmark of mobile devices lets make a drawing app like brushes.
a finger or fingers move across the screen (This message is sent repeatedly as a finger moves.) - (void)touchesMoved:(NSSet
*)touches withEvent:(UIEvent *)event;
a finger or fingers is removed from the screen - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
a system event, like an incoming phone call, interrupts a touch before it ends - (void)touchesCancelled:(NSSet
*)touches withEvent:(UIEvent *)event;
241
242
events added to event queue. A UITouch object created and tracked for a finger. set of UITouches passed. one per
finger. only the moving, begining, or ending event passed. lets make our app.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
243
18
19
20
21
22
23
24
- ( void ) dealloc
{
[ linesInProcess release ];
[ completeLines release ];
[ super dealloc ];
}
- ( void ) clearAll
{
// Clear the collections
[ linesInProcess removeAllObjects ];
[ completeLines removeAllObjects ];
// Redraw
[ self setNeedsDisplay ];
}
- ( void ) drawRect :( CGRect ) rect
{
CGContextRef context = U I G r a p h i c s G e t C u r r e n t C o n t e x t ();
C G C o n t e x t S e t L i n e W i d t h ( context , 10.0);
C GC o n te x t Se t L in e C ap ( context , kCGLineCapRound );
// Draw complete lines in black
[[ UIColor blackColor ] set ];
for ( Line * line in completeLines ){
C G C o n t e x t M o v e T o P o int ( context , [ line begin ]. x , [ line begin ]. y );
C G C o n t e x t A d d L i n e T oP oi n t ( context , [ line end ]. x , [ line end ]. y );
C G Co n t ex t St r o ke P a th ( context );
}
// Draw lines in process in red
[[ UIColor redColor ] set ];
for ( NSValue * v in linesInProcess ){
Line * line = [ linesInProcess objectForKey : v ];
C G C o n t e x t M o v e T o P o int ( context , [ line begin ]. x , [ line begin ]. y );
C G C o n t e x t A d d L i n e T oP oi n t ( context , [ line end ]. x , [ line end ]. y );
C G Co n t ex t St r o ke P a th ( context );
244
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
245
110
111
112
113
114
115
116
117
118
119
120
121
246
Lets use Blocks in ios 4.0 to change colors based on angle and length.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
247
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
1
2
3
}
return self ;
}
- ( void ) dealloc
{
[ color release ];
[ super dealloc ];
}
248
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
- ( void ) colorize
{
// Vertical means more red , horizontal means more green ,
// longer means more blue
// A block variable named colorScheme is created here :
UIColor * (^ colorScheme )( Line *)= ^( Line * l ){
// Compute delta between begin and end points
// for each component
float dx = [ l end ]. x - [ l begin ]. x ;
float dy = [ l end ]. y - [ l begin ]. y ;
// If dx is near zero , red = 1 , otherwise , use slope
float r = ( fabs ( dx ) < 0.001? 1.0: fabs ( dy / dx ));
// If dy is near zero , green = 1 , otherwise , use inv . slope
float g = ( fabs ( dy ) < 0.001? 1.0: fabs ( dx / dy ));
// blue = length over 300
float b = hypot ( dx , dy )/ 300.0;
return [ UIColor colorWithRed : r green : g blue : b alpha :1];
};
// Pass this colorScheme block to the method
// that will iterate over every line and assign
// the computed color to that line
[ self t r a n s f o r m L i n e C o l o r s W i t h B l o c k : colorScheme ];
}
- ( BOOL ) c a n B e c o m e F i r s t R e s p o n d e r
{
return YES ;
}
- ( void ) didMoveToWindow
{
[ self b e c o m e F i rs t R e s p o n d er ];
}
- ( void ) motionBegan :( UIEventSubtype ) motion
withEvent :( UIEvent *) event
{
[ self colorize ];
}
blocks capture variables like anonymous functions in C#. inline block objects (values copied). blocks are an
alternate to callbacks. blocks are used for GCD. kind of like tasks.
grand central dispatch. dispatch queues pools of threads managed.
threads.
1
2
3
4
5
6
7
- ( void ) doCalculation {
/* Do your calculation here */
}
- ( void ) c a l c u l a t i o n T h r e a d E n t r y {
@autoreleasepool {
NSUInteger counter = 0;
while ([[ NSThread currentThread ] isCancelled ] == NO ){
249
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[ self doCalculation ];
counter ++;
if ( counter >= 1000){
break ;
}
}
}
}
- ( BOOL )
1
2
3
4
5
6
7
8
250
1
2
3
4
5
251
6
7
8
9
10
11
12
13
14
15
16
dispatch_queue_t concurrentQueue =
d i s p a t c h _ g e t _ g l o b a l _ q u e u e ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 0);
dispatch_sync ( concurrentQueue , printFrom1To1000 );
dispatch_sync ( concurrentQueue , printFrom1To1000 );
252
Chapter 45
Lecture 45
lets download an image asynchronously.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
dispatch_queue_t concurrentQueue =
d i s p a t c h _ g e t _ g l o b a l _ q u e u e ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 0);
dispatch_async ( concurrentQueue , ^{
__block UIImage * image = nil ;
dispatch_sync ( concurrentQueue , ^{
/* Download the image here */
});
dispatch_sync ( d i s p a t c h _ g e t _m ai n _q u eu e () , ^{
/* Show the image to the user here on the main queue */
});
});
253
254
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
255
generate 10k random numbers if needed. read 10K random numbrs, sort n display. UITableView.
1
2
3
4
- ( NSString *) fileLocation {
/* Get the document folder ( s ) */
NSArray * folders =
N S S e a r c h P a t h F o r D i r e c t o r i e s I n D o m a i n s ( NSDocumentDirectory ,
256
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
dispatch_queue_t concurrentQueue =
d i s p a t c h _ g e t _ g l o b a l _ q u e u e ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 0);
/* If we have not already saved an array of 10 ,000
random numbers to the disk before , generate these numbers now
and then save them to the disk in an array */
dispatch_async ( concurrentQueue , ^{
NSUInteger n u m b e r O f V a l u e sRe qu ir ed = 10000;
if ([ self h a s F i l e A l r ea d y B e e n C r e a t e d ] == NO ){
dispatch_sync ( concurrentQueue , ^{
NSMutableArray * arrayOfRandomNumbers =
[[ NSMutableArray alloc ] initWithCapacity : n u m b e r O f V a l u e s R e q u i r e d ]
NSUInteger counter = 0;
for ( counter = 0;
counter < num be rO fVa lu es Req ui re d ;
counter ++){
unsigned int randomNumber =
arc4random () % (( unsigned int ) RAND_MAX + 1);
[ arrayOfRandomNumbers addObject :
[ NSNumber numb erWi thUns igne dInt : randomNumber ]];
}
/* Now let s write the array to disk */
[ arrayOfRandomNumbers writeToFile :[ self fileLocation ]
atomically : YES ];
});
}
__block NSMutableArray * randomNumbers = nil ;
/* Read the numbers from disk and sort them in an
ascending fashion */
dispatch_sync ( concurrentQueue , ^{
/* If the file has now been created , we have to read it */
if ([ self h a s F i l e A l r e a d y B e e n C r e a t e d ]){
randomNumbers = [[ NSMutableArray alloc ]
in it Wi thC on te nts Of Fi le :[ self fileLocation ]];
/* Now sort the numbers */
[ randomNumbers sortUsingComparator :
257
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78