Professional Documents
Culture Documents
Microsoft Visual Studio 2010 A Beginners
Microsoft Visual Studio 2010 A Beginners
Microsoft Visual Studio 2010 A Beginners
ABeginner’sGuide
About the Author
JoeMayostartedhissoftwaredevelopmentcareerin1986,workingonanRCA
Spectrum70mainframecomputer,programminginassemblylanguagewhereinputwas
viaHollerithcard,outputwasalineprinter,andthedebuggingexperiencewasalight
panelwhereyouhadtopushbuttonstoloadregistersandstepthroughcommands.Since
then,Joehasworkedwithvariousmini-computers,workstations,andPCs.Theoperating
systemshe’sworkedonincludeproprietary,UNIX-based,MS-DOS,andWindows.
Besidesassemblyanddozensofscriptinglanguages,Joehasworkedprofessionallywith
C,C++,VBA,VisualC++,ForteTool,Java,VB.NET,andC#.Inadditiontosoftware
engineering,hehasworkedinmanypositions,includingteamlead,supervisor,manager
(evenrunninga24×7computeroperationscenterwithover50people).Today,Joeruns
hisowncompany,MayoSoftware,providingcustomsoftwaredevelopmentservices
andspecializinginMicrosoft.NETtechnology.HeistheauthorofLINQProgramming
(McGraw-HillProfessional,2008)andotherbooks.Joeisalsotherecipientofmultiple
MicrosoftMVPawards.YoucanfollowJoeonTwitter:@JoeMayo.
ABeginner’sGuide
JoeMayo
NewYorkChicagoSanFrancisco
LisbonLondonMadridMexicoCity
MilanNewDelhiSanJuan
SeoulSingaporeSydneyToronto
Copyright © 2010 by The McGraw-Hill Companies. All rights reserved. Except as permitted under the United States Copyright Act of 1976,
no part of this publication may be reproduced or distributed in any form or by any means, or stored in a database or retrieval system, without
the prior written permission of the publisher.
ISBN: 978-0-07-166896-5
MHID: 0-07-166896-9
The material in this eBook also appears in the print version of this title: ISBN: 978-0-07-166895-8, MHID: 0-07-166895-0.
All trademarks are trademarks of their respective owners. Rather than put a trademark symbol after every occurrence of a trademarked name,
we use names in an editorial fashion only, and to the benefit of the trademark owner, with no intention of infringement of the trademark.
Where such designations appear in this book, they have been printed with initial caps.
McGraw-Hill eBooks are available at special quantity discounts to use as premiums and sales promotions, or for use in corporate training
programs. To contact a representative please e-mail us at bulksales@mcgraw-hill.com.
Information has been obtained by McGraw-Hill from sources believed to be reliable. However, because of the possibility of human or
mechanical error by our sources, McGraw-Hill, or others, McGraw-Hill does not guarantee the accuracy, adequacy, or completeness of any
information and is not responsible for any errors or omissions or the results obtained from the use of such information.
TERMS OF USE
This is a copyrighted work and The McGraw-Hill Companies, Inc. (“McGrawHill”) and its licensors reserve all rights in and to the work. Use
of this work is subject to these terms. Except as permitted under the Copyright Act of 1976 and the right to store and retrieve one copy of the
work, you may not decompile, disassemble, reverse engineer, reproduce, modify, create derivative works based upon, transmit, distribute,
disseminate, sell, publish or sublicense the work or any part of it without McGraw-Hill’s prior consent. You may use the work for your own
noncommercial and personal use; any other use of the work is strictly prohibited. Your right to use the work may be terminated if you fail to
comply with these terms.
THE WORK IS PROVIDED “AS IS.” McGRAW-HILL AND ITS LICENSORS MAKE NO GUARANTEES OR WARRANTIES AS
TO THE ACCURACY, ADEQUACY OR COMPLETENESS OF OR RESULTS TO BE OBTAINED FROM USING THE WORK,
INCLUDING ANY INFORMATION THAT CAN BE ACCESSED THROUGH THE WORK VIA HYPERLINK OR OTHERWISE,
AND EXPRESSLY DISCLAIM ANY WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. McGraw-Hill and its licensors do not warrant
or guarantee that the functions contained in the work will meet your requirements or that its operation will be uninterrupted or error free.
Neither McGraw-Hill nor its licensors shall be liable to you or anyone else for any inaccuracy, error or omission, regardless of cause, in the
work or for any damages resulting therefrom. McGraw-Hill has no responsibility for the content of any information accessed through the
work. Under no circumstances shall McGraw-Hill and/or its licensors be liable for any indirect, incidental, special, punitive, consequential
or similar damages that result from the use of or inability to use the work, even if any of them has been advised of the possibility of such
damages. This limitation of liability shall apply to any claim or cause whatsoever whether such claim or cause arises in contract, tort or
otherwise.
Tomyson,Kamo.
This page intentionally left blank
Contents at a Glance
PARTI UnderstandingVisualStudio2010Essentials
1 IntroducingVisualStudio2010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2 LearningJustEnoughC#orVB.NET:BasicSyntax . . . . . . . . . . . . . . . . . . . . . 35
3 LearningJustEnoughC#andVB.NET:TypesandMembers . . . . . . . . . . . . 67
4 LearningJustEnoughC#andVB.NET:IntermediateSyntax . . . . . . . . . . . 89
PARTII LearningtheVS2010Environment
5 CreatingandBuildingProjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
6 DebuggingwithVisualStudio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
7 WorkingwithData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
PARTIII BuildingProgramswithVS2010
8 BuildingDesktopApplicationswithWPF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
9 CreatingWebApplicationswithASP.NETMVC . . . . . . . . . . . . . . . . . . . . . . . . . 249
vii
viii MicrosoftVisualStudio2010:ABeginner’sGuide
PARTIV EnhancingtheVS2010Experience
12 CustomizingtheDevelopmentEnvironment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
PARTV Appendixes
A IntroductiontoXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
B IntroductiontoXAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
Contents
ACKNOWLEDGMENTS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii
INTRODUCTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix
PARTI UnderstandingVisualStudio2010Essentials
1 IntroducingVisualStudio2010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
WhatIsVisualStudio2010About? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
AutomaticallyGeneratedCode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
RapidCodingExperience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
EverythingatYourFingertips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
CustomizabilityandExtensibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
InstallingVisualStudio2010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
NavigatingtheVisualStudio2010Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
TheMenu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Toolbar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
WorkArea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Toolbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
SolutionExplorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
StatusBar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
ManagingVSWindows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
ExpandingandCollapsingWindows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
DockingWindows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
ix
x MicrosoftVisualStudio2010:ABeginner’sGuide
FloatingWindows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
TabbedWindows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
ClosingandOpeningWindows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
ModifyingEnvironmentSettingsafterSetup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
ExportingSelectedEnvironmentSettings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
ImportingSelectedEnvironmentSettings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
ResettingAllSettings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
FamiliarizationwithVisualStudioProjectTypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
WindowsProjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
WebProjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
OfficeProjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
SharePointProjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
DatabaseProjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2 LearningJustEnoughC#orVB.NET:BasicSyntax . . . . . . . . . . . . . . . . . . . . . 35
StartingaBare-BonesProject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
ExaminingtheCodeSkeleton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
TheMainMethod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
TheProgramClass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
TheFirstProgramNamespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
AnOverviewoftheVSCodeEditor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
ClassandMemberLocators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Bookmarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
SettingEditorOptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
SavingTimewithSnippets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
CodingExpressionsandStatements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
MakingIntellisenseWorkforYou . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
RunningPrograms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
PrimitiveTypesandExpressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Enums . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
BranchingStatements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
3 LearningJustEnoughC#andVB.NET:TypesandMembers . . . . . . . . . . . . 67
CreatingClasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
ClassSyntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
ClassInheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
TheclassSnippet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
WritingMethods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
DeclaringandUsingaMethod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
DeclaringParametersandPassingArguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Contents xi
ReturningDataandUsingMethodResults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
MethodSnippets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
CodingFieldsandProperties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
DeclaringandUsingFields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
DeclaringandUsingProperties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
ThePropertySnippet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
4 LearningJustEnoughC#andVB.NET:IntermediateSyntax . . . . . . . . . . . 89
UnderstandingDelegatesandEvents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
Delegates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Event,Delegate,andHandlerCodeCompletion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
ImplementingInterfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
CreatinganInterface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
MakingClassesImplementtheInterface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
WritingCodeThatUsesanInterface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
TheinterfaceSnippet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
ApplyingArraysandGenerics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
CodingArrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
CodingGenerics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
PARTII LearningtheVS2010Environment
5 CreatingandBuildingProjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
ConstructingSolutionsandProjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
CreatingaNewProject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
NavigatingtheSolutionExplorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
ExaminingPropertySettings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
AssemblyName . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
DefaultNamespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
TargetFramework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
OutputType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
StartupObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
IconandManifest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
AssemblyInformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
ReferencingAssemblies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
Addinga.NETAssemblyReference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
ManagingAssemblyReferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
ReferencingYourOwnClassLibraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
UsingCodeinClassLibraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
xii MicrosoftVisualStudio2010:ABeginner’sGuide
CompilingApplications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
BuildingSolutions/Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
RebuildingSolutions/Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
CleaningSolutions/Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
ManagingDependenciesandBuildOrder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
ManagingCompilationSettings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
NavigatingaProjectwithClassView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
UsingtheClassDesigner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
ClassDesignerVisualization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
ClassDesignerCodeGeneration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
6 DebuggingwithVisualStudio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
ExampleCodeforThisChapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Development-TimeCodeTools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
ConfiguringDebugMode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
SettingBreakpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
CreatingaBreakpoint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
CustomizingaBreakpoint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
ManagingBreakpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
SteppingThroughCode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
InspectingApplicationState . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
LocalsandAutosWindows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
WatchWindows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
TheImmediateWindow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
TheCallStackWindow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
TheQuickWatchWindow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
WatchingVariableswithPinToSource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
WorkingwithIntelliTrace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
SolvingProblemswithVSDebugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
AProgramwithBugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
FindingtheBug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
FixingtheFirstBug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
DebuggingandResolvingNullReferenceExceptionProblems . . . . . . . . . . . . . . . . . 175
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
7 WorkingwithData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
WorkingwithDatabases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
IntroductiontoServerExplorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
CreatingaDatabase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
AddingTables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
RelatingTableswithForeignKeys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
AddingStoredProcedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
ConfiguringDatabaseOptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
Contents xiii
LearningLanguageIntegratedQuery(LINQ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
QueryingObjectCollectionswithLINQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
CreatingaLINQProjectionwithAnonymousTypes . . . . . . . . . . . . . . . . . . . . . . . . . . 198
UsingLINQtoSortCollectionResults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
HandlingDatawithLINQtoSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
SettingUpLINQtoSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
WorkingwiththeLINQtoSQLDesigner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
IntroductiontoQueryingLINQtoSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
PerformingQueriesonMultipleTables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
InsertingDatawithLINQtoSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
UpdatingDatawithLINQtoSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
DeletingDatawithLINQtoSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
PARTIII BuildingProgramswithVS2010
8 BuildingDesktopApplicationswithWPF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
StartingaWPFProject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
UnderstandingLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
GridLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
StackPanelLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
DockPanelLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
WrapPanelLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
CanvasLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
UsingWPFControls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
ManagingWindowsforControls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
SettingProperties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
HandlingEvents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
CodingEventHandlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
WorkingwithDatainWPF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
SettingUpaDataSource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
ConfiguringaComboBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
ReadingandSavingData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
UsingtheDataGrid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
9 CreatingWebApplicationswithASP.NETMVC . . . . . . . . . . . . . . . . . . . . . . . . . 249
UnderstandingASP.NETMVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
StartinganASP.NETMVCProject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
CreatingtheModels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
BuildingControllers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
DisplayingViews . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
LookingInsideaView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
OrganizingViewFiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
xiv MicrosoftVisualStudio2010:ABeginner’sGuide
AssigningMasterPageFiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
PartialViews(a.k.a.UserControls) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
ManagingRouting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
BuildingaCustomerManagementApplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
CreatingaRepository . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
CreatingaCustomerController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
DisplayingaCustomerList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
AddingaNewCustomer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
UpdatingExistingCustomers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
DeletingaCustomer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
10 DesigningSilverlightApplications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
StartingaSilverlightProject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
NavigatingtheSilverlightDesigner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
UsingSilverlightControls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
RunningSilverlightOut-of-Browser(OOB) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
DeployingSilverlightApplications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
11 DeployingWebServiceswithWCF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
StartingaWCFProject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
SpecifyingaContractwithWCFInterfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
ImplementingLogicwithWCFClasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
HostingaWCFService . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
FollowingGeneralHostingProcedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
InstallingIIS7onWindows7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
CreatingaWebSiteonIIS7onWindows7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
DeployingtheWCFServicetoIIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
CommunicatingwithaWCFService . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
CreatingaServiceReference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
CodingWebServiceCalls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
DeployingaClientThatConsumesaWebService . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
CreatingaWebServiceinaWebSite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
PARTIV EnhancingtheVS2010Experience
12 CustomizingtheDevelopmentEnvironment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
ImplementingCustomTemplates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
CreatingNewProjectTemplates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
CreatingNewItemTemplates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
CreatingCustomSnippets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
CreatingaNewSnippet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
ManagingtheSnippetLibrary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
Contents xv
WritingMacros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
RecordingaMacro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
SavingaMacro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
EditingMacros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
13 ExtendingVisualStudio2010 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
CreatingaVisualStudioAdd-In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
RunningtheAdd-InProjectWizard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
ExamininganAdd-InWizardSolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
DrillingintotheConnectClass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
AddingFunctionalitytoanAdd-In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383
ReviewingtheOnConnectionMethod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
ImplementingtheExecMethod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
SettingStatuswithQueryStatus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
DeployinganAdd-In . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
WheretoGoNext . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 0 0
PARTV Appendixes
A IntroductiontoXML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
VS2010XMLEditor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
XMLPrefixes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
XMLElements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
TheXMLMenu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
ConfiguringXMLOptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
B IntroductiontoXAML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
StartingaWPFProject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
ElementsasClasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
AttributesasProperties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
ExecutingtheXAMLDocument . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
PropertyElements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412
MarkupExtensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
This page intentionally left blank
Acknowledgments
A workofthismagnitudeisnevertheramblingsofasingleauthor,butasuccessful
combinationofdedicationfromateamofhighlyskilledprofessionals.Iwouldlike
topersonallythankseveralpeoplewhohelpedmakethisbookpossible.
JaneBrownlow,ExecutiveEditor,helpedkickoffthebookandgotitstartedonthe
rightpath.MeggMorin,AcquisitionsEditor,tookthereinsfromJaneandledtherest
oftheway.JoyaAnthony,AcquisitionsCoordinator,helpedkeeptheflowofchapters
moving.MadhuBhardwaj,ProjectManager,andPattyMon,EditorialSupervisor,helped
coordinatecopyeditsandfinallayout.Iwouldreallyliketothankyouallforyour
patienceandassistance.TherearemanymorepeopleatMcGraw-Hillwhohelpedputthis
booktogether,andIamappreciativeoftheircontributionsandprofessionalism.
RoyOgbornwasthetechnicaleditorforthisbook.I’veknownRoyforseveralyears
andwasdelightedwhenheagreedtotecheditthebook.Besidescatchingmanyofmy
errors,Royprovidedvaluableinsightthatmadeadifferenceinseveralareas,continuously
askingthequestionofwhetherabeginnerwouldunderstandaconcept,whatistheproper
applicationofthelanguagetoaccomplishagoal,andperspectiveonwhatpartsofa
technologyneededemphasis.ThankstoRoyforoutstandingtechnicaleditingandadvice.
xvii
This page intentionally left blank
Introduction
V isualStudiohasbeentheprimaryintegrateddevelopmentenvironment(IDE)for
Microsoftsoftwaredevelopmentforseveralyears.VisualStudio2010(VS),the
subjectofthisbook,isthereforeamatureevolution,buildinguponthesuccessofits
predecessors.ThisbookwillshowyouhowtoleverageVisualStudio2010toyour
advantage,increasingyourskillset,andhelpingyoubecomemoreproductiveinbuilding
software.Thesoftwareyouwilllearntowritewillbefor.NET(pronounced“DotNet”),
whichisaMicrosoftplatformforwritingdifferenttypesofapplications.
Asthetitlesuggests,thisisabookforbeginners.However,therearemanyopinions
aboutwhoabeginneris,solet’sdiscusswhatbeginnermeansinthecontextofthisbook.
Youshouldprobablyhavesomeunderstandingofwhatprogrammingisfromageneral
perspective.Itwouldhelptohaveatleastwrittenabatchfile,macro,orscriptthat
instructedthecomputertoperformsometask.Abeginnercouldalsobesomeonewho
haswrittensoftwarewithtechnology,suchasCobol,Dreamweaver,orJava,butwhois
unfamiliarwithVisualStudio.Whateveryourbackground,thisbookprovidesagradual
on-ramptodevelopingapplicationswithVisualStudio2010.
xix
xx MicrosoftVisualStudio2010:ABeginner’sGuide
Thisbookhas13chaptersandisdividedintofourpartsandacoupleofappendixesas
referencematerial.Thefollowingprovidesanoverviewofeachsection:
● PartI:UnderstandingVisualStudio2010Essentials Chapter1beginswithan
explanationofwhatVSis,itsbenefitstoyou,andwhattypeofapplicationsVSwill
helpyoubuild.Hands-onguidancestartsatthepointofinstallation,givingyoutips
astowhatisbeinginstalledandwhereitgoesonyourcomputer.Chapters2through
4areanintroductiontoC#andVB,twoofthemostwidelyusedprogramming
languagessupportedinVS.Noticethatthetitlesofthesechaptersinclude“Just
Enough,”indicatingthatyouwilllearnthelanguagefeaturesyouneedthroughout
thisbook.Asyouprogressthroughthebook,you’llbeexposedtoallofthelanguage
featuresdiscussedandseehowtheyareused.Evenifyoualreadyknowhowto
program,youmightwanttoperusetheprogramminglanguagechaptersanyway
becauseI’vesprinkledindozensofvaluabletipsthatwillmakeyourcoding
experienceinVSmuchmorepleasurable.
● PartII:LearningtheVS2010Environment Thereareafewuniversaltasksmost
developersperformeveryday,whichincludeworkingwithprojects,debuggingcode,
andmanipulatingdata.WhileChapter5istitled“CreatingandBuildingProjects,”
thereismuchinvolvedwhenworkingwithprojects.Payparticularattentiontothe
guidanceonassembliesandclasslibraries,astheytendtobecomemoreprominent
asyourdevelopmentactivitiesprogressbeyondsimpleprograms.Regardlessofyour
developmentphilosophy,theneedtofixbugshasalwaysexistedandwillcontinue
tobeimportantinthefuture.Chapter6isdesignedtohelpyouusethemanytoolsof
VStofindandfixbugs.Anothercommontaskyou’llhaveisworkingwithdata.VS
allowsyoutocreatedatabases,addtables,andmuchmore.Whenthedatabaseisready
touse,you’lllearnhowtowritecodethatworkswiththedatabase.Ichosetocover
LINQtoSQLbecauseit’soneofthesimplerdatabasetechnologies,yetpowerful
enoughforprofessionalapplicationdevelopment.
● PartIII:BuildingProgramswithVS2010 Withthefoundationsofprogramming
languagesandafeelfortheVSenvironment,you’llbereadytouseVStobuild
applications.The.NETplatformsupportsvarioustechnologies,andthisbooktakes
aforward-lookingapproach,choosingtechnologiesthatwerethemostrecently
introduced.Thefocusinthesechaptersisnottoteachyoueverythingaboutthese
technologies,whichcanfillentirebooksthemselves,butrathertoshowyouhowto
leverageVSinbuildingapplications.You’llgetthefoundationsthatwillgiveyoua
headstartinbuildingyourownapplications.BothChapters8and10useaformof
Introduction xxi
ExtensibleMarkupLanguage(XML)calledXMLApplicationMarkupLanguage
(XAML).Consideringthatthisisabeginner’sbook,Iaddedacoupleofappendixes
thatcoverXMLandXAML.Irecommendthatyoureadtheappendixesbefore
readingChapters8and10.Additionally,youshouldreadChapter8beforereading
Chapter10,becausemanyofthesameconceptsusedtoworkwithWindows
PresentationFoundation(WPF),atechnologyforbuildingdesktopapplications,
areapplicabletoSilverlight,atechnologytobuildWebapplications.Theothertwo
chaptersinthispartwillshowyouhowtobuildWebapplicationswithASP.NET
MVCandhowtocreateWebserviceswithWindowsCommunicationsFoundation.
● PartIV:EnhancingtheVS2010Experience Inadditiontoallofthewizards,
tools,andeditinghelpthatVSoffers,youcanextendVStomakeitworkevenbetter.
Chapter12showsyouhowtocreateyourownprojectandprojectitemwizards,how
tocreatecodesnippetsthatautomaticallygeneratecode,andhowtocreatemacros
thatautomatetheVSenvironment.IfthemacrocapabilityyoulearnaboutinVS
isn’tpowerfulenough,readChapter13,whichshowsyouhowtobuildanAdd-In,
aprogramthatyoucaninstalltoaddnewfeaturestoVS.
FrominstallationtocustomizationoftheIDE,VSisahelpfulandpowerfultool.
IhopeyouenjoythisbookandthatithelpsyoulearnhowtomakeVSworkforyou.
This page intentionally left blank
Part I
Understanding Visual
Studio 2010 Essentials
This page intentionally left blank
Chapter 1
Introducing Visual
Studio 2010
3
4 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● LearnWhatVisualStudio2010CanDoforYou
● InstallandChooseAmongInstallationOptions
● UnderstandWhatTypesofApplicationsYouCanBuild
Y ourfirstexperiencewithVisualStudio(VS)2010isofteninstallation.Aswithmost
software,VSisrathereasytoinstall;thischapterdescribestheinstallationprocess
andgivesyoutipstohelpunderstandavailableoptions.Onceinstallationiscomplete,
you’llopenVSforthefirsttimeandneedtoknowhowtonavigatetheVSenvironment;
thischaptergivesyouahigh-levelviewofhowVSisorganized,howtofindthefeatures
youneed,andhowtoworkwithwindows.Finally,you’lllearnhowtofindthedifferent
applicationtypesthatVShelpsyoubuild.Atthispoint,youknowthatVSwillhelpyou
build.NETapplications,butlet’sstartoffwithamoredetailedexplanationofwhatVS
willdoforyou.
automaticallygeneratedcode.VSoffersmanypremadecontrols,whichincludeskeleton
code,savingyoufromhavingtowriteyourowncodeforrepetitivetasks.Manyofthemore
complexcontrolscontainwizardsthathelpyoucustomizethecontrol’sbehavior,generating
codebasedonwizardoptionsyouchoose.
System Requirements
AsofthiswritingMicrosoftrecommendsyouhavea32-bitx86or64-bit(x64)CPU,
atleast1GBRAM,a5400RPMharddiskdrive,3GBharddiskspace,DVD-ROM,
DirectXvideoat1280×1024resolution,anda1.6GHzprocessor.Recommended
operatingsystemsincludeWindowsVista(allversionsexceptforStarter),WindowsXP
SP2orlater(allversionsexceptforStarter),Windows7(onlyUltimateatthetimethis
chapterwaswritten),Windows2003(SP1orR2orlater),andWindows2008(SP1or
R2orlater).BesuretocheckMicrosoftDeveloperNetwork(MSDN)online,assystem
requirementscanchangeovertime.
1.WhenyoufirstplacetheVSDVDintothedrive,you’llseetheMicrosoftVisualStudio
2010window,showninFigure1-1.AvailableoptionsaretoInstallMicrosoftVisual
Studio2010andCheckForServiceReleases.ClickInstallMicrosoftVisualStudio2010.
2.Thenextwindowyou’llsee,Figure1-2,isthewelcomewindow,titledMicrosoftVisual
Studio2010.Figure1-2showsthatI’minstallingtheUltimateversion.Installationfor
otherversionsissimilar,butthenumberoffeaturesavailabletoinstallvaries.
IfyouchecktheboxonthispageintheHelpImproveSetupsection,theinstaller
willgatherlogsproducedduringthesetupprocessandsendthemacrosstheInternet
toMicrosoftafterthesetupiscomplete.Tohelpyoumakeaninformedchoiceasto
whethertocheckthisbox,thereisaPrivacyStatementlinkunderthecheckboxto
clickandreadifyouwouldlikemoreinformationaboutwhatMicrosoftdoeswith
setupinformation.Whenyou’reready,clickNext.Aftersetupcomponentsareloaded,
you’llseethelicensingscreeninFigure1-3.
8 MicrosoftVisualStudio2010:ABeginner’sGuide
3.InFigure1-3,you’llseewhatcomponentswillbeinstalled.You’llneedtoreadtheVS
licensetoensureyouunderstandwhatthetermsare.Thelicensingtermscandiffer,
dependingonwhattypeofpackageyouacquiredandyourparticularcountryorregion.
Onceyou’vereadthelicense,you’llneedtocheck“Ihavereadandacceptthelicense
terms”toproceed.Next,enterthelicensekeythatcomeswithyoursoftwareandenter
yourname.Theinstallerwillautomaticallyfillintheproductkeyifyoudownloaded
VSviaMicrosoftDeveloperNetwork(MSDN).ClickNextandyou’llseeoptionsfor
customizingproductinstallation.
4.Figure1-4letsyouchoosebetweenfullandcustominstallation.Ifyouclickthe
Customoption,you’llbeabletochoosepreciselywhichcomponentsshouldbe
installed.Thisisagoodopportunitytounchecktheitemsyouwon’teveruse.Ifthisis
Chapter1: IntroducingVisualStudio2010 9
yourfirstinstallationandyouhaveplentyofstorage,youmightwanttogothroughthe
listandcheckeverythingtotakealookatwhatisavailable.Youcanalwaysreturnto
thisinstallationlaterandmakeadjustments.
TheconfigurationscreeninFigure1-4showsthatyoucanalsochangethelocationof
wheretoinstallVS.Takenoteoftheinstallationlocationbecausethisiswhereyouwill
gotofindsamplecode,commonassemblies,andmoreitemsaffectingthedevelopment
environment.Evaluatethediskspacerequirementstoensureyouhaveenoughavailable
storage.You’venowcompletedtheconfigurationoptionsforinstallation.ClickInstallto
starttheinstallation.You’llseeascreensimilartoFigure1-5duringtheinstallationprocess
wherethesmallcheckmarksindicatewhichVScomponentshavesuccessfullyinstalled.
10 MicrosoftVisualStudio2010:ABeginner’sGuide
5.Duringtheinstallation,theVSinstallerwillneedtorebootyourcomputer,showingthe
restartmessageinFigure1-6.Makesureyoucloseanyapplicationsyoucurrentlyhave
opensothatyoudon’tloseyourwork,andthenclickRestartNow.
6.Wheninstallationcompleteswithouterror,you’llseetheSuccesswindow,shownin
Figure1-7.Ifyouhaveerrorsduringinstallation,thiswindowwillgiveyouguidance
onwhattodotosolvetheproblem.
Yourinstallationisnowalmostcomplete.Youcaninstallproductdocumentationby
clickingtheInstallDocumentationbutton,showninFigure1-7.Theinitialinstallation
screenthatappearedwhenbeginningtheinstallationwillreappear,asshowninFigure1-8.
Youshouldalsocheckforservicereleases;notonlyfortheupdatedfunctionalitytoVS,
butalsobecauseservicereleasesoftenincludeimportantsecurityupdates.
YouarenowreadytorunVSforthefirsttime.Atthatpoint,you’llneedtoperform
onemoreeasyconfigurationstep,whereyouwillchooseyourdefaultenvironment
settings,asshowninFigure1-9.
12 MicrosoftVisualStudio2010:ABeginner’sGuide
Thechoiceyoumakefordefaultenvironmentsettingsdependsalotonwhat
languageorenvironmentyou’llusetowritesoftwarein.Theenvironmentsettings
choiceisn’tlockedinstoneandcanberesetifyoudecideyoudon’tlikethesettings.
Alatersectionofthischapter,“ModifyingEnvironmentSettingsafterSetup,”explains
howtochangeenvironmentsettings.ThisbookcoversbothVBandC#,soyouwould
mostlikelywanttochoosethesettingspecifictothelanguageyouwilluse.The
examplesinthisbookwilluseeitherVBorC#settings,dependingonthetopic.The
choiceofsettingsdetermineshowVSwilllayoutthewindowsandthedefaultoptions
thataresetthroughouttheVSIDE.
NOTE
C# or VB, which Should I Choose? Both C# and VB are first-class languages on the
.NET platform. The languages themselves are stripped down to bare syntax, with all
additional services moved into the .NET Framework Class Library, which is common
to all languages. There are a few small differences between the languages, but in
reality, the choice really comes down to personal preference. In practice, knowing
both languages is an advantage because much has been written in articles and books
showing how to use .NET techniques that doesn’t depend on which language was
used. You’ll not want to miss out on excellent content regardless of the language it is
written in.
Youshouldnowhaveagoodinstallationwiththeconfigurationandenvironment
settingsofyourchoosing.WithVSopenforthefirsttime,thenextsectiondescribesthe
high-levelpartsoftheStartpage.
The Menu
AttheverytopleftofFigure1-10,you’llseethemenubar,whichincludesthewords
“File,”“Edit,”“View,”“Tools,”andsoon.Themenubarisastandardpartofmost
windowsapplications.Besidesstandardfilemanagementfunctionality,theFilemenuis
whereyouvisittocreatenewprojects.TheFilemenualsogivesyouaccesstorecently
openedfilesandprojects.
TheEditmenuhasyourstandardcut,copy,andpasteoperations.Italsogivesyou
accesstoabookmarkfeatureforprovidingeasynavigationthroughsourcecode.
ItwouldbeworthyourefforttoexploretheViewmenutoseewhatisavailable,butif
youarejustlearningVisualStudioandhowtowritesoftware,it’sbesttonotclickthese
differentviewsjustyet;we’llexploremostofthoseviewsandwhatthey’reusedforlater.
TheViewmenugivesyouaccesstoallofthetoolwindowsinVS.TheViewmenualso
hasamenuitemnamedOtherWindowsthatincludesmoreapplicationwindowsthatwill
comeinhandyasyoucreatenewsoftware.
Chapter1: IntroducingVisualStudio2010 15
TheToolsmenucontainsagrab-bagoffunctionality;forinstance,youcanattacha
debuggertoseeyourotherprogramsrun,linebyline;connecttoadatabasefordata;set
add-ins,macros,andmore.OneveryimportantmenuitemontheToolsmenuisOptions,
whichexposeshundredsofsettingsforcustomizingyourVSenvironment.
YoucanusetheTestmenutofindallofthefunctionalityforperformingunitteststo
testyournewsoftwareonepartatatime.ThisisalsowhereothereditionsofVSinclude
accesstoothertypesoftestingtools.
TheAnalyze,Architecture,andTeammenushaveadvancedfunctionalityforimproving
theperformanceofanapplication,workingwithapplicationarchitecture,andintegrating
withMicrosoft’sTeamFoundationServer.
TheWindowsandHelpmenusaresimilartomostotherapplicationtypes,wherethe
WindowsmenuallowsyoutomanipulatetheVSwindowsandtheHelpmenuiswhere
youvisittofindthetechnicaldocumentationonVS.
TIP
Many menu items contain shortcut keys that perform the same action as selecting the
menu item. If you are curious about what shortcut keys are associated with a particular
action, you can often find them by opening the menu to see if there are shortcuts
associated with that action. For example, to open the Solution Explorer window and
visit the View menu, the shortcut keys are CTRL-W, S.
Toolbar
BeneaththemenuinFigure1-10,you’llfindatoolbar.Thetoolbarcontainsfrequently
accessedfunctionalitythatisasubsetofwhatisavailableviamenus.Thetoolbarsare
context-sensitive,showingandhidingdependingonwhatyouaredoinginVS.Youcan
displayanytoolbarbyselectingView|Toolbars.
Youcanalsocustomizetoolbarsbyright-clickingthetoolbarofyourchoice,scrolling
tothebottomofthelist,andselectingCustomize.Thetoolbarcustomizationwindow
allowsyoutoaddanyfeatureyouwouldliketothecurrenttoolbar.
Work Area
InthecenterofFigure1-10,youcanseetheStartpage.Thisisthesameareathatyou’ll
usetowritecodeandworkwithvisualdesigners.TheStartpageisdividedintotwo
sections:projectmanagementandinformation.Theprojectmanagementsideofthepage,
ontheleft,offersaquickwaytostartnewprojectsorworkwithalistofrecentlyopened
projects.Theinformationsideofthepage,ontheright,containsresourcestohelpyouget
startedwithVS,suchaslinkstotheMicrosoftWebsite,walkthroughstohelpyoulearn
newfeatures,andatabthatupdateswiththelatestdevelopernewsfromMicrosoft.
16 MicrosoftVisualStudio2010:ABeginner’sGuide
Toolbox
OnthefarleftsideofFigure1-10isaverticaltab,titledToolbox,whichcontainsacontext-
sensitivelistofcontrolsthatcanbedraggedanddroppedontothecurrentdesignersurface.
Theterm“context-sensitive”meansthatcertainitemsarevisibleorhidden,dependingon
whereyou’veclickedlastorwhatcontextyouareworkingin,suchascreatingorediting
anewWebpage.Ifyou’refollowingalong,youdon’thaveadesignersurfaceopenright
now,sotheToolboxisempty.
Solution Explorer
TheSolutionExplorerwindow,totherightoftheStartpageinFigure1-10,iswhereyour
solutions,projects,andprojectitemswillappear.Thisiswhereyoucanfindandorganize
allofthefilesandsettingsthatbelongtoaproject.InFigure1-10,theSolutionExplorer
isblankbecausethereisn’tanopensolution.Ifyouclosethiswindowandneedtofindit
again,justremembertheViewmenudiscussedearlier.
Status Bar
AttheverybottomofFigure1-10istheStatusbar,whichcommunicateswhatishappening
withVSatthecurrenttime.InFigure1-10,theStatusbardisplaystheword“Ready”to
indicateyoucanbeginusingVSatanytime.AsyouworkwithVS,theStatusbarchanges
inacontext-sensitivewaytogiveyouinformationspecifictothetaskyouareworkingon.
Forexample,theeditordisplaysline,column,andotherinformationpertainingtothestatus
oftheeditor.
Managing VS Windows
LookingattheVSscreeninFigure1-10,youcanseehowthewindowsintheworkarea—
Toolbox,Start,andSolutionExplorer—aredecoratedwithvarioustitlebars.Window
titlebarsincludeasetofthreeicons:WindowPosition(downarrow),Maximize/Restore
Down(window),andClose(cross).Figure1-11showstheSolutionExplorerwiththese
threeiconsonitstitlebaratthetop-rightcorner.
TheWindowPositionallowsyoutotreatthewindowasDock,Float,DockAsTabbed
Document,AutoHide,andHide.Youcanexpandawindowtofilltheentireworkareaor
allowthewindowtoberesizedandfloatfreelyaroundtheworkareawiththeMaximize/
RestoreDownicon.Inthedockedposition,theMaximize/RestoreDowniconbecomes
apinthatcanbeusedtopinthewindowopenorallowittoslideshut.TheCloseicon
allowsyoutocloseawindow.Thefollowingsectionsdescribehowusethesetitleiconsto
manipulatethesewindowsthroughexpandingandcollapsing,docking,floating,tabbing,
andclosingandopening.
Chapter1: IntroducingVisualStudio2010 17
IfyoumovethecaratawayfromtheToolbox,theToolboxwillcollapseandturnback
intoatabontheleftsideofthescreen.
Foranycollapsedwindow,suchastheToolbox,youcanexpandthatcollapsed
windowandclicktheHide(pin)icontopinthewindow,whichwillmakethewindow
layoutsimilartotheSolutionExplorer.Figure1-13showsthepinnedwindow;thepinin
theHideicon(abovetheAutoHidetooltip)isverticalandyounolongerseetheToolbox
tabintheleftmargin.
ClickingtheHideicononanyexpandedwindowwillcausethewindowtocollapse
anddisplayasatab,similartotheToolbox.Anotherwaytocollapseawindowisby
selectingtheAutoHideoptionontheWindowPosition(downarrow)menu.
Docking Windows
TheDockoptiondisplaysthewindowinanopendockedposition,similartotheSolution
ExplorerinFigure1-10.Youcanmoveadockedwindowtoanypositioninthework
area.Tomoveadockedwindow,selectitstitlebaranddragthewindowoutofitscurrent
position.Figure1-14showsVSwhenyou’redraggingawindow.
AsshowninFigure1-14,you’llseeavisualsetoficonsappearovertheworkspace,
indicatingthedockingzoneswhereyoucanmovethewindowto.Theshadowofthe
windowwillshowwhatthenewlocationwillbewheneveryoudragawindowintoa
dockingzone.Droppingthewindowintothedockingzonewillmovethewindowfromits
olddockingzoneintothenewdockingzone.
Floating Windows
TheFloatoptionallowswindowstoappearanywhereintheVSIDE,whereyoucanmove
thematwill.Youmoveafloatingwindowbyselectingthefloatingwindow’stitlebarand
movingthecarattothenewlocationwhereyouwantthewindowtobe.Alternatively,
youcandouble-clickonthetitlebar.Figure1-15showstheToolboxfloatingoverother
windows.
20 MicrosoftVisualStudio2010:ABeginner’sGuide
Tabbed Windows
AnexampleofusingtheDockAsTabbedDocumentoptionistheStartpage.Anywindow
setasDockAsTabbedDocumentwillappearasanewtabintheworkarea,alongwithall
theotherwindowssetasDockAsTabbedDocument.Forexample,iftheToolboxisset
asDockAsTabbedDocument,itwillbecomeatabbeddocumentinthesamegroupasthe
Startwindow,asshowninFigure1-16.
TIP
Position windows in a way that makes you most productive. In practice, you probably
don’t want your Toolbox to be a tabbed window. You’ll see examples in later chapters
of this book that drag-and-drop items from the Toolbox to a designer page, which is
also laid out as a tabbed document window. So, trying to drag-and-drop between two
tabbed document windows can be cumbersome. There are several options for working
with Windows in VS, and after working with VS for a while, you’ll want to pick the
layout that works best for you.
Tochangeawindowfromatabbeddocument,selectthetabanddragthewindow
awayfromtheotherdocuments,makingitafloatingwindow.
Chapter1: IntroducingVisualStudio2010 21
ThetwotextboxesinFigure1-19areforafilenameandpathwherethesettingsfile
willbesaved.Noticethatthedefaultfilenameincludesthedate,whichcouldbehelpful
ifyoueverneedtorestoresettings.ClickFinish,whichwillperformtheexportandshow
youtheCompletewindowinFigure1-20aftertheexportoperationisdone.
ClickClosetoclosethewindow.Withanexportedsettingsfile,youoranotherperson
canperformanimportwiththatfile,asdescribedinthenextsection.
openVSandselectTools|ImportandExportSettings,whichopenstheImportandExport
SettingsWizardshowninFigure1-17.Choosethe“Importselectedenvironmentsettings”
optionandclickNexttoviewtheSaveCurrentSettingswindowshowninFigure1-21.
TIP
You can search for various color schemes for Visual Studio on the Internet to
download. One site, at the time of this writing, is http://winterdom.com/2007/11/
vs2008colorschemes; it offers schemes made for Visual Studio 2008 but that also
import into Visual Studio 2010.
26 MicrosoftVisualStudio2010:ABeginner’sGuide
TheSaveCurrentSettingswindowallowsyoutobackupyourcurrentenvironment
settingsbeforechangingthem.Ifyoudoabackup,youwillbeabletorestorelaterincase
somethingdoesn’tworkoutthewayyouintendedwiththeimport.Youcanchoosenotto
backupalso.ClickNexttoviewtheChooseACollectionOfSettingsToImportwindow
inFigure1-22.
AsshowninFigure1-22,youcanimportsomeofthepredefinedsettingsthatare
partofVSundertheDefaultSettingsbranchorimportcustomsettingsundertheMy
Settingsbranch.Customsettingsincludethecurrentsettingsandanyothersettingsthat
you’vesavedtothedefaultpath,showninFigures1-19and1-21.Optionally,youcan
Chapter1: IntroducingVisualStudio2010 27
clickBrowseandnavigatetothelocationwhereasettingsfileislocated.Afterselecting
asettingsfile,clickNext,whichbringsyoutotheChooseSettingsToImportwindow
showninFigure1-23.
TheChooseSettingsToImportwindowallowsyoutospecifyonlythosesettingsthat
youwantinyourenvironment.ItwillonlyupdatethesettingscheckedinFigure1-23.
Allofyourothercurrentsettings,thosethatareuncheckedinFigure1-23,willnotbe
changed.ClickFinishtobegintheimportoperation.Whenimportisdone,you’llseethe
ImportCompletewindow,showninFigure1-24.
28 MicrosoftVisualStudio2010:ABeginner’sGuide
Yourimportisnowcomplete,andyoucanclicktheClosewindow.Anothersettings
optionistoresetyourcurrentsettingstooneoftheVSdefaultoptions,explainednext.
Figure1-25showsthatyoucanselectamongasetofdefaultsettingsforVS.Each
ofthesedefaultsettingsarethesameaswhatyouselectedduringinstallation,previously
showninFigure1-9andtheDefaultSettingsbranchofFigure1-22.Chooseasettingand
clickFinish,whichstartstheresetoperation.Whentheresetisdone,you’llseetheReset
Completewindow,showninFigure1-26.Theresetisnowcomplete,andyoucanclick
Closetoclosethewindowwhenyou’refinished.
Earlierinthechapter,wediscussedprojectsverylightly,butwewillgraduallydig
deeperasthisbookprogresses.Thenextsectiontakesyoualittlebitfurtherbydescribing
whatprojecttypesareavailableinVS.
30 MicrosoftVisualStudio2010:ABeginner’sGuide
NOTE
If you’ve set your environment up for VB, you’ll notice right away that the option to
select is File | New Project, which is only two menu choices, rather than 3 for C#.
While the exact wording and placement of options won’t always match, you can rely on
the functionality being the same, except for when I explain otherwise.
Chapter1: IntroducingVisualStudio2010 31
Inadditiontoanewproject,Figure1-27showsthatyoucancreateanewWebsite,
justopenafileforediting,oropenawizardthatcreatesanewprojectfromexistingfiles.
We’lllookatmanyoftheseoptionslaterinthebook,butlet’stakealookattheNew
Projectwindow,Figure1-28,whichopenedasaresultofselectingFile|New|Project.
TheNewProjectwindowinFigure1-28showsthattherearemanyprojectstoselect
from,includingWindows,Web,Office,SharePoint,Cloud,Reporting,Silverlight,Test,
WCF,andWorkflow.Someoftheseprojecttypesdon’tappearinFigure1-28,butifyou
scrolldowntheTemplateslistintheNewProjectwindow,you’llseethem.Figure1-28
alsoshowstheappearanceforC#projects,buttherearealsosimilarprojectsforother
programminglanguagesthatshipwithVS;includingVB,C++(pronouncedsee-plus-plus),
andF#(pronouncedf-sharp).IfyouhadselectedVBsettingsduringthesetupprocess,
32 MicrosoftVisualStudio2010:ABeginner’sGuide
earlierinthischapter,thedefaultsetofprojecttypeswouldhavebeenVBandC#projects
wouldbelistedintheOtherLanguagesbranch.Thefollowingsectionsdescribethetypes
ofprojectsavailable,someofwhichyou’lllearnhowtocreatelaterinthisbook.
Windows Projects
SelectingWindowsProjectswillshowyoualistofprojecttypesthatcanbecreatedfor
desktopapplications,includingWindowsPresentationFoundation(WPF),Windows
Forms,andConsole.Consoleapplicationsareforbuildingapplicationsthatdon’tneeda
graphicaluserinterface(alsoknownasGUIandpronounced“goo-ee”)andaregenerally
forcreatingutilitiesthatadministratorscanwritescriptswithorforwritingaquicktestfor
yourprogram.You’llbeusingConsoleapplicationswhenlearningVBandC#languages
laterinthisbookbecauseitisasimplewaytoconcentrateonthelanguagewithoutany
distractions.WindowsFormsisanolderdesktopGUItechnology.ThenewdesktopGUI
technologyfor.NETiscalledWPF,whichiscoveredinalaterchapterinthisbook.
Chapter1: IntroducingVisualStudio2010 33
OtherwindowsprojectsincludeWindowsServices,whichareapplicationsthatare
alwaysonandrunasaserviceinthebackgroundwithoutaGUI,ClassLibrariesfor
holdingreusablecodeoftenreferredtoasmiddleware,andControlLibrariesforholding
graphicalcontrolsthatcanbedragged-and-droppedfromtheToolboxontoavisual
designerwithinVS.
Web Projects
WebprojectsincludeASP.NET,ServerControls,WebServices,andDynamicData.An
ASP.NETprojectallowsyoutowriteanapplicationthatishostedbyaWebserver,such
asInternetInformationServer(IIS),andrunsinaWebbrowser.AServerControlproject
enablesyoutobuildalibraryofGUIcontrolsthatcanbedragged-and-droppedontothe
designsurfaceofaWebpageinVS.WebServicesarereusablecomponentsthatyou
cancallfromacrosstheInternet.AnimportantfeatureofWebServicesisthattheyuse
ubiquitousprotocolstoenablecodefromanyplatformtocallthem,facilitatingintegration
amongheterogeneouscomputingsystems.DynamicDataprojectsofferaquickwayto
buildaworkingWebsite,basedonanexistingdatabaseschema.
34 MicrosoftVisualStudio2010:ABeginner’sGuide
Office Projects
Foryears,developershavebeenwritingVisualBasicforApplications(VBA)programs
toautomateMicrosoftOfficeapplications.AnOfficeprojectallowsyoutoautomate
Officeapplicationsthrough.NETusinglanguagessuchasVBandC#.SupportedOffice
applicationsincludeExcel,Word,Project,PowerPoint,Outlook,Visio,andInfoPath.
SharePoint Projects
SharePointisatechnologyforbuildingportal-styleWebapplications.Itisclosely
associatedwithOfficeapplicationsandmanagingworkgroupcollaboration.Inorder
tocreateandrunSharePointprojects,thecomputeryouusetorunVSwillneedtobe
runningoneofMicrosoft’sserverplatforms,suchasServer2008.SharePointdoesnotrun
onWindows7,Vista,orWindowsXP.
Database Projects
DatabaseprojectsincludeaSQLServerprojecttype,offeringcloseintegrationwithSQL
Serverforbuilding.NETcodethatrunsinsideofSQLServer.Forexample,youcanwrite
storedproceduresandfunctionsineitherC#orVBandhavethebenefitofthe.NET
Frameworkinyourcode.VSmakesiteasytodeployyourcodetoSQLServerwitha
singlemouseclick.
Summary
ByknowingthebenefitsofVS,youhaveanappreciationforwhatVScandoforyou,
increasingyourproductivitythroughautomaticallygeneratedcode,rapidcodingand
visualdesign,andextensibility.YoushouldbeabletoinstallVS,choosingtheoptionsthat
preparetheenvironmentspecificallyfortheworkyouwanttodo.Anothersetofskills
yougainedwastheabilitytomanipulatethelayoutofyourenvironmentandmanage
environmentsettings,includinghowtogetyourenvironmentbacktothedefaultsettings
ifyou’vemadetoomanychanges.Havinggrownacquaintedwitheachofthemajor
featuresoftheIDE,youcanopenVSandfindthefeaturesthatyouneed.Withyour
knowledgeoftheadvantagesofVS,properinstallation,andawarenessofVScapabilities,
youarenowreadytostartyourfirstsoftwaredevelopmentproject,whichyou’lllearn
aboutinthenextchapter.
Chapter 2
Learning Just Enough
C# or VB.NET:
Basic Syntax
35
36 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● LearnBasicsofStartingaProject
● UsetheVSEditor
● CodeExpressionsandStatements
T he.NETplatformsupportsseveraldifferentprogramminglanguages.Sinceallofthe
languagesrunonthesameplatformandsharethesameclasslibraries,languagechoice
becomesapersonalchoiceofpreference.Inotherwords,youcanaccomplishthesame
tasks,regardlessofwhatprogramminglanguageyouuse.With.NET,youhaveachoiceof
languagebutretainthesamebenefitsofhavingallofthefeaturesof.NETavailabletoyou.
VisualStudio(VS)2010shipswithfourprogramminglanguages:C#,C++,F#,and
VisualBasic.NET(VB).Thepronunciationofeachoftheselanguages,respectively,isSee
Sharp,SeePlusPlus,EffSharp,andVeeBee.C#andVBarethetwomostpopular.NET
programminglanguagesandhavethegreatestsupportinVS.Therefore,thisbookusesboth
C#andVBinallexamples.Whileyoumaychooseoneoftheselanguagesasyourfavorite,
thereisgreatbenefitinknowingboth.Mostofwhatiswrittenonline,inmagazines,and
inbookscontainsexamplesforeitherC#orVB,andsometimes,butnotalways,both.You
mightnotwanttomissgreatcontentbecauseofalimitedlanguagechoice.
Chapter1dancedaroundprojectsandwhatisavailable.Itwasimportanttohavethat
overview,butI’msureyou’reeagertoseesomecode.Thischapterwillbesatisfyingin
thatyou’lllearnhowtocreateaproject,seewhatcodeisgenerated,andlearnhowtoadd
codeyourself.Thisisthefirstchapterofthreethatcoverslanguagesyntax,combining
eachlanguagefeaturewithtipsonhowVShelpsyoucode.You’llstartoffbycreatinga
simpleprojectandthenlearnaboutlanguagetypesandstatements.
Togetstarted,openVSandselectFile|New|Project.You’llseetheNewProject
window,showninFigure2-1.YourfirsttaskistoselectConsoleApplicationasthe
programtype.ThensettheprogramnametoFirstProgramandspecifyalocationofyour
choiceforwheretheprojectwillbecreated.OtherfeaturesoftheNewProjectwindow
includetheabilitytospecifythe.NETFrameworkversion,sortingoptions,iconsize
options,andasearchcapability.
NOTE
It’s often useful to choose a project location other than the default. The default is your
personal “My Documents” folder, which is long to type, cumbersome to navigate to, and
error prone. Choosing a shorter path helps alleviate these problems. If you’re working
on a team with other developers, it’s also helpful to use a common location for projects
where everyone has their files in the same location.
NOTE
In the example code that accompanies this book, the projects are named
FirstProgramCS (containing C# examples) and FirstProgramVB (containing VB
examples). You’ll see this convention, specifying the language in the project name suffix,
in all of the code examples accompanying this book.
38 MicrosoftVisualStudio2010:ABeginner’sGuide
AlongtheverytopcenterofthedialogshowninFigure2-1,the.NETFramework
isthesetofclasslibraries,runtime,andlanguagesthatisthedevelopmentplatform
supportedbyVS.VSallowsyoutotargetmultipleversionsofthe.NETFramework,
includingversions2.0,3.0,3.5,and4.0.VSwillcompileyourcodeagainsttheversion
youchoose.Generally,you’llwanttobeginallnewprojectswiththelatestversion,4.0,
becauseyou’llwanttobeabletousethenewestandmostproductive.NETfeatures.The
primaryreasonforusinganearlierversionisifyoumustperformworkoncodethatis
alreadywrittenforanearlierversionof.NET.Thesortingandsearchingfeaturestothe
rightofthisselectionenableyoutofindprojecttypesindifferentways,whicheverismost
comfortableforyou.
ClickingOKwillproduceaConsoleapplicationprojectintheprogramminglanguage
youchose,whichyoucanseeintheSolutionExplorer,showninFigure2-2.TheSolution
ExplorerinFigure2-2containsasolution,whichisacontainerformultipleprojects.
Later,you’llgainastrongerappreciationfortheroleofthesolutionwhenorganizing
projectstosupportasoftwareapplication.UnderthesolutionistheFirstProgramproject.
WithintheFirstProgramprojectareprojectitems,suchasfilesandsettings.Many
differenttypesofprojectitemscangointoaproject,andthespecificprojectitemsthatgo
intoaprojectdependontheprojecttype.Forexample,thereareprojectitemsthatarepart
ofaWPFapplicationbutwouldn’tbepartofaConsoleapplication.Ofparticularinterest
intheFirstProgramprojectisthefilenamedProgram.cs(orModule1.vbifprogramming
inVB),whichisacodefile,aswe’lldiscussinthenextsection.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
classProgram
{
staticvoidMain(string[]args)
{
}
}
}
VB:
ModuleModule1
SubMain()
EndSub
EndModule
40 MicrosoftVisualStudio2010:ABeginner’sGuide
TheskeletoncodeinListing2-1iswhatVScreatedwhenthenewConsoleapplication
wascreated.Itistheretogiveyouaheadstartonwritingyourprogram.Whatyounow
haveisawholecomputerprogram.Thisprogramdoesn’tdomuchofanythingatthis
point,butitwillactuallyrunandthenenditself.Lookingatthewholeprogram,youcan
seethattherearesetsofnestedcurlybracesintheC#code.TheVBcodehasModuleand
SubwithcorrespondingEndidentifierstoindicatetheboundariesofablock.Thebraces
inC#codealwayscomeinpairsanddefineablock.Thefollowingexplanationworks
fromtheinsideouttohelpyouunderstandwhatthiscodemeans.
thatbelongtoeachinstance.IfanobjectsuchasCustomerhasmethodsthatbelongto
eachinstance,thosemethodsarenotstatic.However,iftheCustomerobjecttypehasa
methodthatisstatic,thentherewouldonlybeasinglecopyofthatmethodthatisshared
amongallCustomerobjects.Forexample,whatifyouwantedtogetadiscountprice
forallcustomers,regardlessofwhothecustomeris;youwoulddeclareastaticmethod
namedGetCustomerDiscount.However,ifyouwantedinformationthatbelongedto
aspecificcustomer,suchasanaddress,youwouldcreateaninstancemethodnamed
GetAddressthatwouldnotbemodifiedasstatic.
VBusesthetermshared,whichhasthesamemeaningasstatic.Modulesare
inherentlyshared,andallmodulemethodsmustbeshared.Therefore,theVBMain
methodisshared.
InC#,thecurlybracesdefinethebeginandendoftheMainmethod.InVB,Main
beginswithSubandisscopedtoEndSub.Next,noticethattheC#Mainmethodis
enclosedinsideofasetofbracesthatbelongtosomethingcalledaclassthathasbeen
giventhenameProgram.TheVBMainmethodisenclosedinsomethingcalledamodule.
You’lllearnabouttheenclosingclassandmodulenext.
classProgram
{
//MainMethodomittedforbrevity
}
VB:
ModuleModule1
'Mainomittedforbrevity
EndModule
Mostobjecttypesyoucreatewillbeaclass,asshowninthepreviousC#example.
InVB,youwouldreplaceModulewithClass.AlthoughVSusesModuleasthedefault
objecttypeforanewproject,it’saholdoverfromearlierversionsofVB.Inpractice,you
shouldn’tusetheVBModulebutshouldpreferClass.TheProgramclasscontainsthe
Mainmethod.YoucouldaddothermethodstotheProgramclassorModule1module,
42 MicrosoftVisualStudio2010:ABeginner’sGuide
whichyou’llseemanytimesthroughoutthisbook.TheConsoleapplicationdefinedthe
skeletoncodeclasstohavethenameProgram.Inrealityyoucannametheclassanything
youwant.Whatevernamesyouchooseshouldmakesenseforthepurposeoftheclass.
Forexample,itmakessenseforaclassthatworkswithcustomerstobenamedCustomer
andonlycontainmethodsthathelpyouworkwithcustomers.Youwouldn’taddmethods
forworkingdirectlywithinvoices,products,oranythingotherthancustomersbecause
thatwouldmakethecodeinyourCustomerclassconfusing.Classesareorganizedwith
namespaces,whicharediscussednext.
namespaceFirstProgram
{
//Programclassomittedforbrevity
}
Youcanputmanyclassesinsideofanamespace,whereinsidemeanswithinthe
beginningandendingbracesforanamespace.
Chapter2: LearningJustEnoughC#orVB.NET:BasicSyntax 43
TheusingdirectivesatthetopoftheC#partofListing2-1arereallyashortcutthat
makesiteasierforyoutowritecode.Forexample,theSystemnamespacecontainsthe
Consoleclass.IftheusingSystemdirectivewerenotpresent,youwouldberequired
towriteSystem.Console.WriteLineinsteadofjustConsole.WriteLine.Thiswasashort
example,butusingdirectivescanhelpcleanupyourcodeandmakeitmorereadable.
AVBmodulemustbedeclaredatthegloballevel,meaningthatitcan’tbeaddedto
anamespacethatyoucreate.ThefollowingexampledemonstrateswhataVBnamespace
lookslike:
NamespaceFirstProgram
PublicClassCustomer
EndClass
EndNamespace
Inthisexample,youcanseethattheFirstProgramnamespacecontainsaCustomer
class.Thenexttaskyou’llwanttotakeoniswritingcode,butbeforedoingso,let’slook
atsomeofthefeaturesoftheVSCodeeditor.
ThefollowingsectionsexaminevariouselementsoftheCodeeditor,startingwith
classandmemberlocators.
Bookmarks
Figure2-3showsabookmarkonthelinefortheprogramclass.Bookmarksallowyouto
navigatecodequicklywithoutmanualnavigationwhenworkingwithmultipledocuments
ormultiplelocationswithinthesamedocument.Table2-1showsalistofkeyboard
commandsforbookmarks.
KeyCode Meaning
CTRL-B, T Toggle a bookmark on or off
CTRL-B, N Move to next bookmark
CTRL-B, P Move to previous bookmark
CTRL-B, C Clear all bookmarks
CTRL-W, B Open the Bookmarks window
OneoftheentriesinTable2-1,CTRL-W,BopenstheBookmarkswindowshownin
Figure2-4,allowingyoutomanagebookmarksthroughoutyourapplication.
Thebookmarkhasatoolbar,whichisthesametoolbarthatappearsinVSwhenthe
editorwindowisactive.TheactionsonthetoolbarincludetheitemsfromTable2-1,plus
theabilitytomovebetweenfolders.
WithintheBookmarklist,youcanchecktomakeabookmarkactiveorinactive.When
thebookmarkisinactive,previousandnextnavigationwillnotstopatthebookmark.You
canchangethenameofthebookmarkbyclickingthenametwice.TheFileLocationand
LineNumbertellyouwherethebookmarkislocated.
TIP
If you want to share your custom editor settings, you can use the Import and Export
Settings Wizard that you learned about in Chapter 1. There is also an Import And
Export Settings branch right below Fonts And Colors in the Options window.
Mosteditorcustomizationsareinalanguage-specificbranchoftheOptionswindow.
Figure2-6showstheoptionsavailableforC#programmers.
46 MicrosoftVisualStudio2010:ABeginner’sGuide
TheOptionswindowinFigure2-6isopenedtoTextEditor,C#,FormattingNew
Lines.Asyoucansee,thereareverydetailedsettingsforevenhowtheeditorautomatically
formatsnewlinesandwherebracesappear.Ifthecodedoesn’tformatthewayyouwantit
to,visitthispagetosettheoptionstowhatyouplease.
NOTE
The CTRL-ALT-SPACE keystroke in Figure 2-7 switches between the Intellisense modes
Consume First and Standard mode. In Standard mode, which shows CTRL-ALT-SPACE,
typing characters automatically selects keywords. However, there are situations where
you are trying to type a word that doesn’t exist yet and Intellisense is too aggressive by
adding the selected completion list item, instead of what you typed. In those cases, you
can press the CTRL-ALT-SPACE keys to go to Consume First mode and what you’ve typed will
be selected. You can still use the DOWN ARROW key on your keyboard in Consume First
mode to select the highlighted term in the completion list.
Youcanidentifysnippetsinthecompletionlistbythetornpapericon.Atthispoint,
youcanpresstheTABkeytocompletethenamespacekeyword.ThenpressTABagainto
produceatemplatewhereyoucanfilloutthehighlightedfields.Figure2-8showsthe
resultsofcreatinganamespacesnippetbytypingnandpressingTAB,TAB.
AsshowninFigure2-8,youwouldtypeintheNamespacenameinthehighlighted
formfieldtoreplaceMyNamespace,whichisplaceholdertext.Fortemplateswithmore
fields,youwouldpresstheTABkeytomovebetweenfields.Inthecaseofthenamespace
showninFigure2-8,thereisonlyonefieldinthetemplatetocomplete.
VBoffersacoupleofwaystoaddsnippets:bytypingprefixesorviaapicklist.Tosee
howVBsnippetswork,placeyourcaratinsideoftheModule1module,underneathEnd
Main(notinsideoftheMainblock).TypeSuandpressTAB,andnoticethatVScreatesa
Sub(method)alongwithatemplatecontainingafieldforfillingouttheSubsnippet.
AnotherwaytoaddVBsnippetsistotypea?andpressTAB.You’llreceiveapicklist,
asshowninFigure2-9.Youcannavigatethispicklisttofindthesnippetyouneed,as
classifiedinoneofthefolders.VBshipswithmanymorebuilt-insnippetsthanforC#.
Nowthatyouknowhowtousesnippets,let’smoveontothedifferenttypesof
statementsyoucanhaveinC#andVBandhowsnippetsworkwiththosestatements.
VB:
Console.WriteLine("HellofromVisualStudio2010!")
ThefollowingstepsshowyouhowVShelpsyousavekeystrokes:
1.InsidethebracesoftheMainmethod,typecandnoticehowtheIntellisensewindow
appears,withalistofallavailableidentifiersthatstartwithc.Thislistiscalleda
completionlist.
2.Typeoandnoticethatthecompletionlistfiltersallbutthoseidentifiersthatbegin
withco.
3.Typenandyou’llseethattheonlyidentifieravailableisConsole.Thisiswhatwe
want,andyouonlyneededtotypethreecharacterstogetthere.
4.AtthispointmostpeoplepresstheENTERorTABkeytoletVSfinishtypingConsole,
butthatiseffectivelyawasteofakeystroke.
50 MicrosoftVisualStudio2010:ABeginner’sGuide
YouknowthatthereisadotoperatorbetweenConsoleandWriteLine,sogoahead
andtypetheperiodcharacter,whichcausesVStodisplay“Console.”intheeditorand
showyouanewcompletionlistthatcontainsmembersoftheConsoleclassthatyou
cannowchoosefrom.
NOTE
So, I’ll admit that I spent a couple paragraphs trying to explain to you how to save a
single keystroke, but that’s not the only thing you should get out of the explanation.
The real value is in knowing that there are a lot of these detailed options available to
increase your productivity. Every time you take advantage of a new VS option, you
raise the notch of productivity just a little higher.
5.NowtypewriteandnoticethatbothWriteandWriteLineappearinthecompletionlist.
NowtypetheletterlandnoticethatWriteLineistheonlyoptionleftinthecompletionlist.
NOTE
If you’ve typed WriteLine a few times, you’ll notice that the completion list goes straight
to WriteLine after a few characters, rather than just Write. This is because Intellisense
remembers your most frequently used identifiers and will select them from the list first. If
you continue to type, Intellisense will then highlight those identifiers with exact matches.
Notice the checked option in Figure 2-10; Intellisense preselects most recently used
members, showing that this behavior is turned on by default.
6.Saveanotherkeystrokeandpressthe(keytoletVSfinishtheWriteLinemethodname.
7.Atthispoint,youcanfinishtypingthestatement,resultinginaMainmethodthatlooks
likethis:
C#:
staticvoidMain(string[]args)
{
Console.WriteLine("HellofromVisualStudio2010!");
}
VB:
SubMain()
Console.WriteLine("HellofromVisualStudio2010!")
EndSub
Ifyou’reaC#developerandwanttochangeIntellisenseoptions,openTools|Options
andselectTextEditor|C#|Intellisense,andyou’llseetheIntellisenseoptionsinFigure2-10.
Thisoptionisn’tavailableforVB.
Chapter2: LearningJustEnoughC#orVB.NET:BasicSyntax 51
Noticethatthereisatextboxtitled“Committedbytypingthefollowingcharacters,”
whichcontainsasetofcharactersthatwillcauseVStotypetherestoftheselected
identifierinthecompletionlistplusthecharacteryoutyped.ReferringbacktoStep4,this
ishowyouknowthataperiodcommitsthecurrentselection.
Younowhaveaprogramthatdoessomething;itcanprintamessagetotheconsole.
Thenextsectionwillexplainhowyoucanrunthisprogram.
Running Programs
InVS,youcanrunaprogrameitherwithorwithoutdebugging.Debuggingisthe
processoffindingerrorsinyourcode.Ifyourunwithdebugging,you’llbeabletoset
breakpointsandstepthroughcode,aswillbedescribedinChapter6.Runningwithout
debuggingallowsyoutoruntheapplication,avoidinganybreakpointsthatmighthave
beenset.
Torunwithoutdebugging,eitherselectDebug|StartWithoutDebuggingorpress
CTRL-F5.ThiswillruntheCommandPromptwindow,whereyou’llseethewords“Hello
fromVisualStudio2010!”orwhateveryouaskedthecomputertowrite,onthescreen.
TheCommandPromptwindowwillstayopenuntilyoupressENTERorclosethewindow.
52 MicrosoftVisualStudio2010:ABeginner’sGuide
Torunwithdebugging,eitherselectDebug|StartDebuggingorpressF5.Because
ofthewaytheapplicationiscodedsofar,theCommandPromptwindowwillquickly
runandclose;youmightmissitifyoublinkyoureyes.Topreventthis,youcanadda
Console.ReadKeystatementbelowConsole.WriteLine,whichwillkeepthewindowopen
untilyoupressanykey.Here’stheupdatedMainmethod:
C#:
staticvoidMain(string[]args)
{
Console.WriteLine("HellofromVisualStudio2010!");
Console.ReadKey();
}
VB:
SubMain()
Console.WriteLine("HellofromVisualStudio2010!")
Console.ReadKey()
EndSub
PressingF5willshow“HellofromVisualStudio2010!”ontheCommandPrompt
window,justaswhenrunningwithoutdebugging.
Tounderstandwhytherearetwooptions,thinkaboutthedifferencebetweenjust
runningaprogramanddebugging.Ifyourunaprogram,youwantittostayopenuntil
youcloseit.However,ifyouaredebuggingaprogram,youhavemostlikelyseta
breakpointandwillstepthroughthecodeasyoudebug.Whenyourdebuggingsessionis
over,youwanttheprogramtoclosesothatyoucanstartcodingagainrightaway.
NowthatyouknowhowtoaddcodetotheMainmethodandrunit,youcanbegin
lookingatthebuildingblocksofalgorithms,startinginthenextsection.
Primitive Types
Youcandefinevariablesinyourprogramswhosetypeisoneoftheprimitivetypes.
Variablescanholdvaluesthatyoucanread,manipulate,andwrite.Therearedifferent
typesofvariables,andthetypespecifieswhatkindofdatathevariablecanhave.In.NET
thereareprimitivetypes(akabuilt-in)andcustomtypes.Thecustomtypesaretypesthat
youcreateyourselfandarespecifictotheprogramyouarewriting.Forexample,ifyou
arewritingaprogramtomanagethecustomersforyourbusiness,thenyouwouldcreate
atypethatcouldbeusedasthetypeofavariableforholdingcustomertypes.You’ll
Chapter2: LearningJustEnoughC#orVB.NET:BasicSyntax 53
VB C# .NET Description
Byte byte Byte 8-bit unsigned integer
SByte sbyte SByte 8-bit signed integer
Short short Int16 16-bit signed integer
UInt16 ushort UInt16 16-bit unsigned integer
Integer int Int32 32-bit signed integer
UInt32 uint UInt32 32-bit unsigned integer
Long long Int64 64-bit signed integer
UInt64 ulong UInt64 64-bit unsigned integer
Single float Single 32-bit floating point
Double double Double 64-bit floating point
Boolean bool Boolean true or false
Char Char Char 16-bit Unicode character
Decimal decimal Decimal 96-bit decimal (used for money)
String string String String of Unicode characters
learnhowtocreatecustomtypeslater.First,youneedtolearnaboutprimitivetypes.The
primitivetypesarepartoftheprogramminglanguagesandbuiltinto.NET.Aprimitive
typeisthemostbasictypeofdatathatyoucanworkwithin.NET,whichcan’tbebroken
intosmallerpieces.Incontrast,acustomtypecanbemadeupofoneormoreprimitive
types,suchasaCustomertypethatwouldhaveaname,anaddress,andpossiblymorebits
ofdatathatareprimitivetypes.Table2-2liststheprimitivetypesanddescriptions.
LookingatTable2-2,rememberthatC#iscase-sensitiveandalloftheprimitivetypes
arelowercase.Youcanalsoseeathirdcolumnfor.NETtypes.Occasionally,you’llsee
codethatusesthe.NETtype,whichaliasestheC#andVBlanguage-specifictypes.The
followingexampleshowshowtodeclarea32-bitsignedintegerinbothC#andVB,along
withthe.NETtype:
C#:
intage1;
Int32age2;
VB:
Dimage1asInteger
Dimage2asInt32
54 MicrosoftVisualStudio2010:ABeginner’sGuide
ConsistentwithTable2-2,C#usesintandVBusesIntegerastheirnativetype
definitionsfora32-bitsignedinteger.Additionally,youseeagedefinedinbothC#and
VBusingthe.NETtype,Int32.Noticethatthe.NETtypeisthesameinbothlanguages.
Infact,the.NETtypewillalwaysbethesameforeverylanguagethatrunsin.NET.Each
languagehasitsownsyntaxforthe.NETtypes,andeachofthelanguage-specifictypesis
saidtoaliasthe.NETtype.
Expressions
Whenperformingcomputationsinyourcode,you’lldosothroughexpressions,whichare
acombinationofvariables,operators(suchasadditionormultiplication),orreferencing
otherclassmembers.Here’sanexpressionthatperformsamathematicalcalculationand
assignstheresulttoanintegervariable:
C#:
intresult=3+5*7;
VB:
DimresultAsInt32=3+5*7
AvariablethatwasnamedresultinthisexampleisaC#typeintoraVBtypeInt32,
asspecifiedinTable2-2.Thevariablecouldbenamedprettymuchanythingyouwant;
Ichosethewordresultforthisexample.ThetypeofournewvariableresultintheVB
exampleisInt32,whichisaprimitive.NETtype.YoucouldhaveusedtheVBkeyword
Integer,whichisanaliasforInt32instead.Theexpressionis3+5*7,whichcontains
theoperators+(addition)and*(multiplication)andiscalculatedandassignedtoresult
whentheprogramruns.Thevalueofresultwillbe38becauseexpressionsusestandard
algebraicprecedence.Intheprecedingexample,5*7iscalculatedfirst,multiplication
hasprecedence,andthatresultisaddedto3.
Youcanmodifytheorderofoperationswithparentheses.Here’sanexamplethatadds
3to5andthenmultipliesby7:
C#:
intdifferentResult=(3+5)*7;
VB:
DimdifferentResultAsInt32=(3+5)*7
Becauseofthegroupingwithparentheses,differentResultwillhavethevalue56after
thisstatementexecutes.
Chapter2: LearningJustEnoughC#orVB.NET:BasicSyntax 55
C#:
intbankAccount=0;
stringaccountString=bankAccount==0?"checking":"savings";
VB:
DimaccountStringAsString=
IIf(bankAccount=0,"checking","saving")
TheconditionalpartofthisoperatorevaluatesifbankAccountisequalto0ornot
whentheprogramruns(commonlyknownas“atruntime”).Whenevertheconditionis
true,thefirstexpression,theonefollowingthequestionmarkforC#orfollowingthe
commaforVB,“checking”inthiscase,willbereturned.Otherwise,ifthecondition
evaluatestofalse,thesecondexpression,followingthecolonforC#orafterthesecond
commaforVB,willbereturned.Thatreturnedvalue,eitherthestring“checking”or
“savings”inthiscase,isassignedtotheaccountStringvariablethatwasdeclared.
NOTE
In earlier versions of the VB programming language, you were required to place an
underline at the end of a statement that continued to the next line. In the latest version
of VB, line continuations are optional. If you’ve programmed in VB before, the missing
statement continuation underline might have caught your attention, but it is now
perfectly legal.
Enums
Anenumallowsyoutospecifyasetofvaluesthatareeasytoreadincode.Theexample
I’lluseistocreateanenumthatliststypesofbankaccounts,suchaschecking,savings,
andloan.Tocreateanenum,openanewfilebyright-clickingtheproject,selectAdd|
NewItem|CodeFile,callthefileBankAccounts.cs(orBankAccounts.vb),andyou’ll
haveablankfile.TypetheenuminListing2-3.
56 MicrosoftVisualStudio2010:ABeginner’sGuide
C#:
publicenumBankAccount
{
Checking,
Saving,
Loan
}
VB:
EnumBankAccount
Checking
Saving
Loan
EndEnum
Listing2-4showshowyoucanusetheBankAccountenum:
C#:
BankAccountaccountType=BankAccount.Checking;
stringmessage=
accountType==BankAccount.Checking?
"BankAccountisChecking":
"BankAccountisSaving";
VB:
DimaccountTypeAsBankAccount=BankAccount.Checking
Dimmessage=
IIf(accountType=BankAccount.Checking,
"BankAccountisChecking",
"BankAccountisSaving")
Chapter2: LearningJustEnoughC#orVB.NET:BasicSyntax 57
TheaccountTypeenumvariableisaBankAccountandisinitializedtohavethevalue
oftheCheckingmemberofBankAccount.Thenextstatementusesaternaryoperator
tocheckthevalueofaccountType,evaluatingwhetheritisChecking.Ifso,messageis
assignedwiththefirststring.Otherwise,messageisassignedwiththesecondstring.Of
course,weknowit’sthefirststringbecausetheexampleissosimplethatyoucanseeitis
codedthatway.
Branching Statements
Abranchingstatementallowsyoutotakeonepathofmany,dependingonacondition.
Forexample,considerthecaseforgivingacustomeradiscountbasedonwhetherthat
customerisapreferredcustomer.Theconditioniswhetherthecustomerispreferredor
not,andthepathsaretogiveadiscountorchargetheentireprice.Twoprimarytypesof
branchingstatementsareifandswitch(SelectCaseinVB).Thefollowingsectionsshow
youhowtobranchyourlogicusingifandswitchstatements.
Expressions
Ifstatementsallowyoutoperformanactiononlyifthespecifiedconditionevaluatesto
trueatruntime.Here’sanexamplethatprintsastatementtotheconsoleifthecontentsof
variableresultisgreaterthan48usingthe>(greaterthan)operator:
C#:
if(result>48)
{
Console.WriteLine("resultis>48");
}
VB:
Ifresult>48Then
Console.WriteLine("Resultis>48")
EndIf
C#curlybracesareoptionalifyouonlyhaveonestatementtorunaftertheifwhen
theconditionevaluatestotrue,butthecurlybracesarerequiredwhenyouwanttwoor
morestatementstorun(alsoknownas“toexecute”)shouldtheconditionbetrue.The
conditionmustevaluatetoeitheraBooleantrueorfalse.Additionally,youcanhavean
elseclausethatexecuteswhentheifconditionisfalse.Aclauseisjustanotherwayto
saythatanitemisapartofanotherstatement.Theelsekeywordisn’tusedasastatement
58 MicrosoftVisualStudio2010:ABeginner’sGuide
itself,sowecallitaclausebecauseitcanbepartofanifstatement.Anexampleofan
elseclauseisshownhere:
C#:
if(result>48)
{
Console.WriteLine("resultis>48");
}
else
{
Console.WriteLine("resultis<=48");
}
VB:
Ifresult>48Then
Console.WriteLine("Resultis>48")
Else
Console.WriteLine("Resultis<=48")
EndIf
Astheprecedingexampleshows,ifresultisnotgreaterthan48,thenitmustbeless
thanorequalto48.
AsshowninFigure2-11,thetemplatebringsyoutoahighlightedfieldforspecifying
theconditionoftheifstatement.ForC#,typetheconditionyouwantevaluatedandpress
ENTER;thesnippetcompletesbyplacingyourcaratwithintheifstatementblock.ForVB,
justplaceyourcursorwhereyouwanttobegintypingnext.
InC#,theelsestatementsnippetissimilartoif.TypeelseandpressTAB,TAB—the
elsetemplateappearswiththecaratbetweentheblocksoftheelse.Thereisn’taVBelse
snippet;justtypeElsebetweenthelaststatementoftheIfandtheEndIf.
Switch/Select Statements
Aswitchstatement(SelectCasestatementforVB)tellsthecomputertoevaluateoneor
manyconditionsandbranchappropriately.Here’sanexamplethatwillperformdifferent
actionsdependingonthevalueofanamevariable:
C#:
varname="Megan";
switch(name)
{
case"Joe":
Console.WriteLine("NameisJoe");
break;
case"Megan":
Console.WriteLine("NameisMegan");
break;
default:
Console.WriteLine("UnknownName");
break;
}
VB:
DimnameAsString="Megan"
SelectCasename
Case"Joe"
Console.WriteLine("NameisJoe")
Case"Megan"
Console.WriteLine("NameisMegan")
CaseElse
Console.WriteLine("Unknownname")
EndSelect
IntheC#example,youcanseethekeywordswitchwiththevaluebeingevaluated
inparentheses.Thecodetoexecutewillbebasedonwhichcasestatementmatchesthe
switchvalue.Thedefaultcaseexecuteswhenthereisn’tamatch.Thebreakkeyword
60 MicrosoftVisualStudio2010:ABeginner’sGuide
isrequired.Whentheprogramexecutesabreakstatement,itstopsexecutingtheswitch
statementandbeginsexecutingthenextstatementafterthelastcurlybraceoftheswitch
statement.
FortheVBexample,theSelectCasestatementusesnameastheconditionand
executescodebasedonwhichcasematchesname.TheCaseElsecodeblockwillrunif
noothercasesmatch.
switch(name)
{
default:
break;
}
VBSelectstatementsworksimilartotheC#switch;typeSeandpressTAB,TAB;you’ll
seetheVBtemplateshowninFigure2-14.
InC#,younormallyjustaddthecasestatementsyouneed.However,thereisaspecial
featureoftheswitchsnippetthatmakesitevenmoreefficienttouseenums,creatinga
caseforeachenumvalueautomatically.Inthefollowingexample,weusetheaccountType
variableoftheenumtypeBankAccountfromListing2-3.Toseehowtheswitchstatement
workswithenums,typeswandpressTAB,TAB;you’llseetheswitchtemplatewiththe
conditionfieldhighlighted.TypeaccountTypeinthefieldandpressENTER.Theswitch
snippetwillautomaticallygeneratecasesforeachoftheBankAccountenummembers
asfollows:
switch(accountType)
{
caseBankAccount.Checking:
break;
caseBankAccount.Saving:
break;
caseBankAccount.Loan:
break;
default:
break;
}
Theenumcomesthroughasaconveniencethatiseasytoreadandminimizespotential
spellingmistakeswhenusingstrings.Nowthatyouknowhowbranchingstatementswork,
let’smoveontoloops.
Loops
Youcanperformfourdifferenttypesofloops:for,foreach,while,anddo.Thefollowing
sectionsexplainhowloopswork.
For Loops
Forloopsallowyoutospecifythenumberoftimestoexecuteablockofstatements.
Here’sanexample:
C#:
for(inti=0;i<3;i++)
{
Console.WriteLine("i="+i);
}
VB:
ForiAsInteger=0To2
Console.WriteLine("i="&i)
Next
62 MicrosoftVisualStudio2010:ABeginner’sGuide
IntheprecedingC#loop,iisavariableoftypeint,theloopwillcontinuetoexecute
aslongasiislessthan3,andiwillbeincrementedbyoneeverytimeaftertheloop
executes.Thecondition,i<3,isevaluatedbeforetheloopexecutes,andtheloopwillnot
executeiftheconditionevaluatestofalse.
TheVBForloopinitializesiasaninteger,iterating(repeating)threetimesfrom
0to2,inclusive.
NOTE
The + and & operators from the preceding code example perform string concatenation.
Although i is an integer, it will be converted to a string prior to concatenation.
Thesamekeysequence(fo,TAB,TAB)worksforVBForloopsnippetstoo,exceptthat
you’llseethesnippettemplateinFigure2-16.
TheC#forloopsnippettemplateisdifferentfromprevioustemplatesinthatyou
havetwofieldstofillout.First,nameyourindexer,whichdefaultstoi,andthenpress
TAB,whichmovesthefocustotheloopsizefield,containingLengthastheplaceholder.
Ifyoulikethevariablenamei,whichisanunderstoodconvention,justpresstheTAB
keyandsetthelengthoftheloop.You’llendupwithaforloopandthecaratinside
oftheblock.
andholdobjectsinmemoryindifferentforms,whichcouldbeStack,List,Queue,and
more.Here’sanexamplethatloopsonanarrayofstrings:
C#:
string[]people={"Megan","Joe","Silvia"};
foreach(varpersoninpeople)
{
Console.WriteLine(person);
}
VB:
Dimpeople={"Megan","Joe","Silvia"}
ForEachpersonAsStringInpeople
Console.WriteLine(person)
Next
Inthisexample,peopleisanarrayofstringsthatcontainsthreespecificstringsof
text.Theblockoftheloopwillexecutethreetimes,onceforeachiteminthearray.Each
iterationthroughtheloopassignsthecurrentnametoperson.
While Loops
Awhileloopwillallowablockofcodetoexecuteaslongasaspecifiedconditionistrue.
Here’sanexamplethatdoesacountdownofnumbers:
C#:
intcount=3;
while(count>0)
{
Console.WriteLine("count:"+count);
count--;
}
VB:
DimcountAsInteger=3
Whilecount>0
Console.WriteLine("count:"&count)
count-=1
EndWhile
Thewhileloopexecutesaslongascountisgreaterthan0.Sincecountis3andwill
decrementbyoneeachtimethroughtheloop,thevaluewillchangefrom3to2to1and
thentheloopwon’texecuteanymore.Becarefulnottocreateendlessloops.
Do Loops
Youcanuseadoloopifyouwantthecodeinthelooptoexecuteatleastonetime.Here’s
anexamplethatdemonstratesasimplemenuthatobtainsuserinput:
C#:
stringresponse="";
do
{
Console.Write("Press'Q'andEntertobreak:");
response=Console.ReadLine();
}while(response!="Q");
VB:
Do
Console.Write("PressQandEntertobreak:")
response=Console.ReadLine()
LoopWhileresponse<>"Q"
Inthisexample,you’llalwaysgetthepromptforPress‘Q’andEntertobreak:.The
Console.ReadLinereadstheuserinput,whichisoftypestring.Iftheinputisastringthat
containsonlyacapitalQ,theloopwillend.
VBhasanothervariationofloopsthatusetheUntilkeyword,asfollows:
Do
Console.Write("PressQandEntertobreak:")
response=Console.ReadLine()
LoopUntilresponse="Q"
Inthiscode,youcanseethattheUntilconditionwillcontinueloopingwhilethe
conditionisnottrue,whichisoppositeoftheDoLoopWhile.
FillintheconditiononthedoloopandpressENTER,placingthecaratinthe
doloopblock.
ForaVBDosnippettype?,TAB,C,ENTER,C,ENTER,anduseanarrowkeytoselect
thevariantofDoloopthatyouwant.Figure2-22showsanexampleoftheDoLoop
Whiletemplate.
Summary
Workingwithlanguagesisacoreskillwhenbuilding.NETapplications.Twoofthemost
usedlanguagesin.NETareC#andVB,whichiswhythischapterisdedicatedtothose
twolanguages.Youlearnedabouttypes,expressions,statements,codeblocks,conditions,
andbranching.Additionally,youlearnedsomeoftheessentialfeaturesofVSforwriting
code,suchasthecodeeditor,bookmarks,Intellisense,andsnippets.
Chapter3takesyoutothenextstepinyourlanguagejourney,teachingyouabout
classesandthevariousmembersyoucancodeaspartofclasses.
Chapter 3
Learning Just Enough
C# and VB.NET:
Types and Members
67
68 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● CreateClasses
● WriteMethods
● CodeFieldsandProperties
A typeisageneraltermforclasses,modules,enums,andmore.Thischapterwill
specificallydiscusstheclasstype,whichallowsyoutocreateyourowncustomtypes.
You’llalsoseethevalueofaclasswhenyoulearnaboutclassmembers.You’llseehow
thefield,method,andpropertyclassmemberscanbeused.We’llstartwithlearninghow
tocreateanduseclasses.
Creating Classes
Previously,youlearnedabouttheprimitivetypes,whicharebuiltintolanguagesandalias
theunderlying.NETtypes.Youcanalsocreateyourowntypes,viaclasses,whichyou
caninstantiateandcreateobjectswith.Thefollowingsectionexplainshowtocreate
aclassandtheninstantiateanobjectfromit.
Class Syntax
Tocreateanewcustomclassdefinition,right-clicktheproject,selectAdd|Class,name
theclassEmployeeforthisexample,andtypethefileextension.csforC#or.vbforVB;
thenclickAdd(VSwilladdthisfileextensionforyouifyoudon’t).You’llseeafilewith
thesamecodeasListing3-1.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
Chapter3: LearningJustEnoughC#andVB.NET:TypesandMembers 69
{
publicclassEmployee
{
publicstringFirstName;
}
}
VB:
PublicClassEmployee
PublicDimFirstNameAsString
EndClass
TheC#EmployeeclassisnearlythesameastheProgramclassthatyoucreatedinthe
precedingchapter,exceptthattheclassnamehereisEmployee.InVB,you’veonlycreated
amodulebefore,andtheEmployeeclassisyourfirstclassforthisbook.Youcanadd
memberstoaclass,whichcouldbeevents,fields,methods,andproperties.Listing3-1shows
anexampleofafield,FirstName,andyou’lllearnaboutevents,methods,andpropertiesin
latersectionsofthischapter.Afieldisavariableinaclassthatholdsinformationspecificto
thatclass.
Listing3-2showshowtoinstantiateanobjectoftypeEmployee,whichisyournew
customtype,anduseit.YouwouldputthiscodeinsideofMainoranothermethod.You’ll
learnmoreaboutmethodsinthelatersection“WritingMethods.”
C#:
Employeeemp=newEmployee();
emp.FirstName="Joe";
VB:
DimempAsNewEmployee
emp.FirstName="Joe"
InListing3-2,youcanseethatempisavariabledeclaredastypeEmployee.TheC#
newEmployee()orVBNewEmployeeclausecreatesanewinstanceofEmployee,andyou
canseethatthisnewinstanceisbeingassignedtoemp.Withthatnewinstance,viatheemp
variable,youcanaccesstheEmployeeobject,includingitsinstancemembers.InListing3-2,
theFirstNamefieldofthatparticularinstanceofEmployeeisassignedastringvalueof"Joe".
Hereyouseethatanobjectcancontaindata.
70 MicrosoftVisualStudio2010:ABeginner’sGuide
Nowthatyoucandefineanewclass,createaninstancefromthatclass,anduseit,the
nextsectionshowsyouanotherfeatureofclassescalledinheritance.
Class Inheritance
Oneclasscanreusethemembersofanotherthroughafeatureknownasinheritance.In
programmingterms,wesayachildclasscanderivefromaparentclassandthatchild
classwillinheritmembers(suchasfieldsandmethods)oftheparentclassthattheparent
classallowstobeinherited.ThefollowingexamplewillcreateaCashierclassthat
derivesfromtheEmployeeclass.Tocreatethisclass,right-clicktheproject,selectAdd|
Class,andnametheclassCashier.Listing3-3showsthenewclassandmodificationsfor
implementinginheritance.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
publicclassCashier:Employee
{
}
}
VB:
PublicClassCashier
InheritsEmployee
EndClass
TheC#inheritancerelationshipisindicatedbythecolonaftertheCashieridentifier,
followedbytheclassbeingderivedfrom,Employee.InVB,youwritethekeyword
Inherits,onanewline,followedbytheclassbeingderivedfrom.Essentially,thismeans
thatCashierhasallofthesamemembersasEmployee.Listing3-4demonstratesthe
benefitsofinheritance.
Chapter3: LearningJustEnoughC#andVB.NET:TypesandMembers 71
C#:
Cashiercashr=newCashier();
cashr.FirstName="May";
VB:
DimcashrAsNewCashier
cashr.FirstName="May"
AccordingtoListing3-4,CashierdoesnothaveafieldnamedFirstName.However,
EmployeedoeshaveaFirstNamefieldandCashierderivesfromEmployee.Because
ofinheritance,CashierautomaticallyinheritsFirstName,andthecodeinListing3-4is
perfectlylegal.Inheritancecanbethoughtofasspecializationinthesensethat,inthis
example,CashierisaspecializedkindofEmployee.Totakeadvantageofthisspecialization,
youcouldaddanewfieldtoyournewCashierclasscalled“assignedCashRegister”where
now,notonlydoestheCashierclasshavethefieldsandmethodsofEmployee,itisableto
holdthevalueforaspecificcashregisternameornumber.AninstanceoftheEmployee
classwouldnotbeabletocontainthisinformation.The.NETFrameworkusesinheritance
extensivelytoofferyoureusableclasslibraries.
TIP
You can often use the phrase “is a” to describe the relationship between inherited
classes when starting from the child class. For example, you can say “Cashier is an
Employee.” If you apply this phrase technique to your software design and the sentence
sounds logically correct, then you’ve probably used inheritance correctly.
JusttypeintheclassnameinthefieldandpressENTER.Thecaratwilllocatetothe
insideoftheclassblock.Nowthatyouknowhowtocreateclasses,you’llneedtoknow
howtoaddmembers,startingwithmethods.
Writing Methods
Youcandivideyouralgorithmsintoblocksofcodecalledmethods.Indifferentprogramming
languages,methodsarecalledfunctions,procedures,orsubroutines.I’llusethetermmethod
asagenericterm,exceptwhenIneedtobemorespecific.You’vealreadyusedmethods
whencodingConsole.WriteLine,whereWriteLineisamethodoftheConsoleclass.A
methodcontainsoneormorestatements.Reasonsforcreatingmethodsincludetheabilityto
modularizeyourcode,isolatecomplexoperationsinoneplace,orgroupacommonoperation
thatcanbereusedinmultipleplaces.Thefollowingsectionsshowyouhowtodeclareand
usemethods.
C#(Program.cs)
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
classProgram
{
staticvoidMain(string[]args)
{
MessagePrintermsgPrint=newMessagePrinter();
msgPrint.PrintMessageInstance();
}
}
Chapter3: LearningJustEnoughC#andVB.NET:TypesandMembers 73
C#:(MessagePrinter.cs)
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
classMessagePrinter
{
publicstaticvoidPrintMessageStatic()
{
Console.WriteLine("Hellofromastaticmethod.");
}
publicvoidPrintMessageInstance()
{
Console.WriteLine("Hellofromaninstancemethod.");
}
}
}
VB(Module1.vb):
ModuleModule1
SubMain()
MessagePrinter.PrintMessageShared()
DimmsgPrintAsNewMessagePrinter()
msgPrinter.PrintMessageInstance()
EndSub
EndModule
VB(MessagePrinter.vb)
PublicClassMessagePrinter
PublicSharedSubPrintMessageShared()
Console.WriteLine("Hellofromasharedmethod.")
EndSub
PublicSubPrintMessageInstance()
Console.WriteLine("Hellofromaninstancemethod.")
EndSub
EndClass
74 MicrosoftVisualStudio2010:ABeginner’sGuide
Listing3-5hastwotypesofmethods,staticandinstance.InVB,sharedmethodsare
thesameasstatic.Youcantellwhichtypeofmethodeachisbecausestaticmethodshave
thestaticmodifier(sharedinVB),butinstancemethodsdon’thaveastatic(orsharedin
VB)modifier.First,let’slookatthestatic(shared)methoddeclaration,andthenyou’llsee
howit’scalled.
Thestatic(sharedinVB)method,PrintMessageStatic(PrintMessageSharedinVB)
hasapublicaccessmodifier,whichmeansthatanyothercodeusingthecontainingclass,
MessagePrinter,willbeabletoseethemethod.Ifyoudidn’tincludethepublicaccess
modifier,themethodwouldautomaticallydefaulttobeingprivateandonlyothercode
residingwithintheMessagePrinterclasswouldbeabletousethatmethod.
PrintMessageStatichasavoidkeyword,meaningthatthismethoddoesnotreturna
value.InVB,youindicatethatamethoddoesnotreturnavaluebymakingitaSub,as
wasdoneinListing3-5.Later,you’lllearnhowtocreateamethodthatdoesreturnvalues
toitscallingcodethatinvokesthismethod.Theemptyparameterlistappendedtothe
PrintMessageStatic(PrintMessageSharedinVB)meansthattherearenotanyparameters
forthismethod.Parametersallowcallerstopassinformationtothemethod;asubject
we’lldiscusssoon.
Withinthemethodblock,youcanseethatthereisaConsole.WriteLinestatement.
Youcanaddasmanystatementsasyouneedforthepurposeofthemethod.Next,we’ll
examinehowPrintMessageStatic(PrintMessageSharedinVB)iscalled,whichthe
followingcoderepeatsfromListing3-5:
C#:
Program.PrintMessageStatic();
VB:
MessagePrinter.PrintMessageShared()
Viewingtheprecedingexample,whichshowsastatementinsideoftheMainmethod,
youcanseethecalltoProgram.PrintMessageStatic(PrintMessageSharedinVB).
Noticethattheclass(akatype)thatcontainsallthemethodsisnamedMessagePrinter.
InC#,astaticmethodiscalledthroughitscontainingtype,whichiswhyyoucall
PrintMessageStaticwiththeProgramprefix.InVB,youcaninvokesharedmethods
througheitherthemethod’stypeoraninstanceofthattype.Wediscussinstance
methodsnext.
Thenextmethod,PrintMessageInstance,isaninstancemethod;ithasnostatic
modifier.TherestofthemethoddefinitionmirrorsthatofthePrintMessageStaticmethod.
Chapter3: LearningJustEnoughC#andVB.NET:TypesandMembers 75
SincePrintMethodInstanceisaninstancemethod,youcallitdifferently;throughan
instanceofitscontainingtype,whichthefollowingcoderepeatsfromListing3-5:
C#:
MessagePrintermsgPrint=newMessagePrinter();
msgPrint.PrintMessageInstance();
VB:
DimmsgPrintAsNewMessagePrinter()
msgPrinter.PrintMessageInstance()
Asthisexampleshows,thetypeofmsgPrintisMessagePrinter.Usingthestatementnew
MessagePrintercreatesanewinstanceofMessagePrinteratruntime,whichisassignedtothe
msgPrintvariable.Nowthatyou’vecreatedaninstanceofaMessagePrinterandmsgPrint
hasareferencetothatinstance,youcancalltheinstancemethod,PrintMessageInstance,via
themsgPrintvariable.Next,let’slookathowtoaddparameterstoamethodanddiscusswhy
that’simportant.
C#(Program.cs):
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
classProgram
{
staticvoidMain(string[]args)
76 MicrosoftVisualStudio2010:ABeginner’sGuide
{
MessagePrintermsgPrint=newMessagePrinter();
string[]customerNames={"Jones","Smith","Mayo"};
stringreportTitle="ImportantCustomerReport";
msgPrint.PrintCustomerReport(customerNames,reportTitle);
}
}
C#(MessagePrinter.cs):
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
publicvoidPrintCustomerReport(
string[]customers,stringtitle="CustomerReport")
{
Console.WriteLine(title);
Console.WriteLine();
foreach(varnameincustomers)
{
Console.WriteLine(name);
}
}
}
}
VB(Module1.vb):
ModuleModule1
SubMain()
DimmsgPrintAsNewMessagePrinter()
DimcustomerNames={"Jones","Smith","Mayo"}
DimreportTitleAsString="ImportantCustomerReport"
msgPrint.PrintCustomerReport(customerNames,reportTitle)
EndSub
EndModule
Chapter3: LearningJustEnoughC#andVB.NET:TypesandMembers 77
VB(MessagePrinter.vb):
PublicClassMessagePrinter
SubPrintCustomerReport(ByValcustomersAsString(),ByValtitle
AsString)
Console.WriteLine(title)
Console.WriteLine()
ForEachnameIncustomers
Console.WriteLine(name)
Next
EndSub
EndClass
Parametersareacomma-separatedlistofidentifiers,alongwiththetypeofeach
identifier,whichclearlyindicateswhattypeofparameterthemethodisexpecting.In
Listing3-6,thePrintCustomerReportmethodhastwoparameters:titleoftypestringand
customersoftypestringarray.Themethoddisplaysthetitleintheconsolewindowwhen
youruntheprogram,displaysablankline,andtheniteratesthroughthelist,displaying
eachcustomernametotheconsole.
YoucanseehowtheMainmethodcreatesanewinstanceofMessagePrinter,
whichmsgPrintpointsto,andthencallsPrintCustomerReportusingmsgPrint.The
argumentsbeingpassed,reportTitleandcustomerNames,matchthepositionandtypes
oftheparametersforPrintCustomerReport,whichareofthecorrecttypesthatthe
PrintCustomerReportmethodisexpecting.
Intheprecedingexample,thecallingcodemustprovidearguments,actualdata,
forallparameters.However,youcanspecifyparametersasbeingoptional,allowing
youtoomitargumentsfortheoptionalparametersifyoulike.Here’samodificationto
PrintCustomerReportwherethetitlebecomesanoptionalparameter:
C#:
publicvoidPrintCustomerReport(
string[]customers,stringtitle="CustomerReport")
{
Console.WriteLine(title);
Console.WriteLine();
foreach(varnameincustomers)
{
Console.WriteLine(name);
}
}
78 MicrosoftVisualStudio2010:ABeginner’sGuide
VB:
SubPrintCustomerReport(
ByValcustomersAsString(),
OptionalByValtitleAsString="CustomerReport")
Console.WriteLine(title)
Console.WriteLine()
ForEachnameIncustomers
Console.WriteLine(name)
Next
EndSub
Theprecedingcoderequirescallerstopassanarrayofcustomers,butitdoesnot
requireatitle.Whenwritingmethods,optionalparametersmustbelistedlast.Here’s
amethodcallwithouttheoptionalparameter:
C#:
custProg.PrintCustomerReport(customerNames);
VB:
msgPrint.PrintCustomerReport(customerNames)
Becausethecallerdidn’tpassanargumentfortitle,thevalueoftitleinsideof
PrintCustomerReportbecomesthedefaultvalueassignedtothetitleparameter.
Inadditiontopassingargumentstomethods,youcanreceivevaluesreturnedfrom
methods.
C#(Program.cs):
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
Chapter3: LearningJustEnoughC#andVB.NET:TypesandMembers 79
namespaceFirstProgram
{
classProgram
{
staticvoidMain(string[]args)
{
CalcmathProg=newCalc();
intsquaredInt=mathProg.SquareInt(3);
Console.WriteLine("3squaredis"+squaredInt);
Console.ReadKey();
}
}
}
C#(Calc.cs):
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
publicclassCalc
{
publicintSquareInt(intnumber)
{
returnnumber*number;
}
}
}
VB(Module1.vb):
ModuleModule1
SubMain()
DimmathProgAsNewCalc()
DimsquaredIntAsInteger=mathProg.SquareInt(3)
Console.WriteLine("3squaredis"&squaredInt)
EndSub
EndModule
80 MicrosoftVisualStudio2010:ABeginner’sGuide
VB(Calc.vb):
PublicClassCalc
PublicFunctionSquareInt(ByValnumberAsInteger)AsInteger
Returnnumber*number
EndFunction
EndClass
FortheC#example,noticehowthereturntypeoftheSquareIntmethodistypeint,
ratherthanthekeywordvoidthatwasusedinourmethodsbefore.Wheneveryouspecify
areturntype,themethodmustreturnsomethingwhosetypeisthesameasthereturn
typedeclared.Intheprecedingexample,thereturntypeisdeclaredasint;therefore,the
methodguaranteesthattheresultofthecalculationistypeint.TheMainmethodhas
acoupleofstatementsthatinvokethismethodanddisplaytheresultstotheconsole.
IntheVBexample,themethodisnowaFunction.Submethodsdon’treturnvalues.
NoticehowthefunctionsignatureappendsAsIntegeraftertheparameterlist,which
indicatesthatthereturntypeofthefunctionisInteger.
Method Snippets
C#doesn’thavesnippetsforwritingmethods(althoughyoucouldcreateyourown
snippets),butVBdoes.InVB,typeSub,TAB,TAB;producingthetemplateshownin
Figure3-2;orFun,TAB,TAB;producingthetemplateshowninFigure3-3.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
classProgram
{
privatedecimalaccountBalance=100m;
staticvoidMain(string[]args)
{
Programaccount=newProgram();
account.Credit(100m);
account.Debit(50m);
Console.WriteLine("Balance:"+account.CurrentBalance);
Console.ReadKey();
}
82 MicrosoftVisualStudio2010:ABeginner’sGuide
publicvoidCredit(decimalamount)
{
accountBalance+=amount;
}
publicvoidDebit(decimalamount)
{
accountBalance-=amount;
}
publicdecimalCurrentBalance
{
get
{
returnaccountBalance;
}
set
{
if(value<0)
{
//chargefee
}
accountBalance=value;
}
}
}
}
VB:
ModuleModule1
PrivateDimaccountBalanceAsDecimal=100
SubMain()Credit(100)
Debit(50)
Console.WriteLine("Balance:"&CurrentBalance)
Console.ReadKey()
EndSub
SubCredit(ByValamountAsDecimal)
accountBalance+=amount
EndSub
SubDebit(ByValamountAsDecimal)
accountBalance-=amount
EndSub
Chapter3: LearningJustEnoughC#andVB.NET:TypesandMembers 83
PublicPropertyCurrentBalance()AsDecimal
Get
ReturnaccountBalance
EndGet
Set(ByValvalueAsDecimal)
Ifvalue<0Then
'chargefee
EndIf
accountBalance=value
EndSet
EndProperty
EndModule
LookatwhereaccountBalanceisdeclared:atthebeginningoftheProgram(Module1
inVB)classblock.ItisatthesamescopeasMainandothermethods,meaningthatitisa
memberofProgram(Module1inVB),justlikeMain,Credit,andDebit.Whenvariables
likeaccountBalancearedeclaredasclassmembers,asopposedtolocalvariablesthat
aredeclaredinsideofmethodblocks,theyarecalledfields.TheaccountBalanceistype
decimal,whichisagoodchoiceforholdingfinancialvalues.
TheaccountBalancefieldhasaprivatemodifier,whichmeansthatitcanonlybeusedby
membersofthesameclass.TheimplementationsofCreditandDebit,respectively,increase
anddecreasethevalueofaccountBalance.SinceCreditandDebitaremembersofthesame
classasaccountBalance,they’reallowedtoreadfromandwritetoaccountBalance.
MaininvokesCreditandDebittochangethevalueoftheaccountBalancefield.
Additionally,MaindisplaysthevalueofaccountBalanceintheconsolewindowthrough
apropertynamedCurrentBalance.ThenextsectionexplainshowtheCurrentBalance
propertyworks.
set
{
if(value<0)
{
//chargefee
}
accountBalance=value;
}
VB:
PublicPropertyCurrentBalance()AsDecimal
Get
ReturnaccountBalance
EndGet
Set(ByValvalueAsDecimal)
Ifvalue<0Then
'chargefee
EndIf
accountBalance=value
EndSet
EndProperty
Propertieshaveaccessors,namedgetandset,thatallowyoutoaddspeciallogic
whenthepropertyisused.Whenyoureadfromaproperty,onlythegetaccessorcode
executes,andthesetaccessorcodeonlyexecuteswhenyouassignavaluetoaproperty.
Intheprecedingexample,thegetaccessorreturnsthevalueofcurrentBalancewithno
modifications.Ifthereweresomelogictoapply,likecalculatinginterestinadditiontothe
currentbalance,thegetaccessormighthavecontainedthelogicforthatcalculationprior
toreturningthevalue.Thesetaccessordoeshavelogicthatchecksthevaluetoseeifitis
lessthanzero,whichcouldhappenifacustomeroverdrewhisorheraccount.Ifthevalue
islessthanzero,thenyoucouldimplementlogictochargethecustomerafeeforthe
overdraft.Thevaluekeywordcontainsthevaluebeingassignedtotheproperty,andthe
previoussetaccessorassignsvaluetotheaccountBalancefield.Thefollowingstatement
fromtheMainmethodinListing3-8readsfromCurrentBalance,effectivelyexecutingthe
getaccessor,whichreturnsthevalueofcurrentBalance:
C#:
Console.WriteLine("Balance:"+account.CurrentBalance);
VB:
Console.WriteLine("Balance:"&CurrentBalance)
Chapter3: LearningJustEnoughC#andVB.NET:TypesandMembers 85
SincetheCurrentBalancepropertyreturnsthevalueoftheaccountBalancefield,
theConsole.WriteLinestatementwillprintthevaluereadfromCurrentBalancetothe
commandline.
Manyofthepropertiesyou’llwritewillsimplybewrappersaroundcurrentobject
statewithnootherlogic,asinListing3-9.
C#:
privatestringm_firstName;
publicstringFirstName
{
get
{
returnm_firstName;
}
set
{
m_firstName=value;
}
}
VB:
Privatem_firstNameAsString
PublicPropertyFirstName()AsString
Get
Returnm_firstName
EndGet
Set(ByValvalueAsString)
m_firstName=value
EndSet
EndProperty
InListing3-9,youcanseethatm_firstName,commonlyreferredtoasabacking
field,isaprivatevariableandthattheFirstNamepropertyonlyreturnsm_firstName
fromthegetaccessorandassignsthevaluetom_firstNameinthesetaccessor.Since
thisissocommon,youcansavesyntaxbyusinganautomaticproperty,asshownin
Listing3-10.
86 MicrosoftVisualStudio2010:ABeginner’sGuide
C#:
publicstringFirstName{get;set;}
VB:
PublicPropertyFirstNameAsString
Theautomaticproperty,FirstName,islogicallyequivalenttotheexpandedFirstName
withaccessorsandbackingfield.Behindthescenes,thecompilerproducestheexpanded
versionwherethebackingfieldisguaranteedtohaveauniquenametoavoidconflicts.
Donotoverlookthatwhenyouuseautomaticproperties,youcannotaddyourowncode
thatrunsinsidethegetorsetaccessors.
Summary
Youarenowabletocreateclassestodefineyourowncustomtypes.Afterlearninghow
tocreateclassesanduseclassinstances,alsoknownasobjects,youlearnedhowtoadd
fields,methods,andpropertiestoyourclassdefinition.Themethodsdiscussionwasmore
in-depth,showingyouhowtodefineparametersandreturnvalues.Youalsolearnedhow
todefinebothauto-implementedandnormalproperties,andyoulearnedalittleabout
classinheritance.
Thenextchaptermovesyouupalevelinlanguageskillsbyshowingyouhowto
createanothertype,calledaninterface.You’llalsolearnhowtoaddanothertypeofclass
member,events.
This page intentionally left blank
Chapter 4
Learning Just Enough
C# and VB.NET:
Intermediate Syntax
89
90 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● UseDelegatesandEvents
● ImplementInterfaces
● CodewithArraysandGenerics
Inpreviouschapters,youlearnedbasicsyntaxandhowtocreateyourowntypes.This
chapterroundsoutthebareessentialsofwhatyouneedtoknowwithdelegatesand
events,interfaces,andaquickintroductiontoarraysandgenerics.Thismaterialdoesn’t
attempttobetooadvanced,butgivesyouenoughinformationtounderstandthelanguage
conceptsinvolved.You’llseealloftheselanguagefeaturesbeingusedthroughoutthe
book,andit’sgoodtohavesomebackgroundonwhattheymean.Let’sstartoffwith
delegatesandevents.
ThenextsectionwilladdmorelogictothesetaccessorinCurrentBalanceinthenext
listingandraiseaneventforthecallingcode.
Events
Aneventisatypeofclassmemberthatallowsyourclassorclassinstancetonotifyanyother
codeaboutthingsthathappenwithinthatclass.Tohelpyouunderstandtheuseofevents,
thissectionwillassociateaneventwiththeaccountBalanceofanaccount.Listing4-1isa
modifiedversionofListing3-8fromChapter3.Itadditionallyhasaneventandlogicthat
raisestheevent.
Toseehowaneventcanbeuseful,consideraprogramthatusesaclassthatmanages
accounts.Therecouldbedifferenttypesofaccounts,suchascheckingorsavings.Ifa
customerperformsanoverdraft,theconsequencesprobablyvarybywhattypeofaccount
isbeingused.However,allyouwantisageneralizedaccountclassthatcanbeusedby
anybankaccounttypeanddoesn’tknowwhattheoverdraftrulesare,whichmakesthe
classmorereusableindifferentscenarios.Therefore,youcangivetheaccountclassan
eventthatwillfireoffanotificationwheneveranoverdraftoccurs.Then,withinyour
specializedcheckingaccountclassinstance,forexample,youcanregistersomething
calledaneventhandlersothattheinstanceoftheclassknowseachtimetheoverdraft
eventoccursviathehandler.
InListing4-1,theCurrentBalancepropertyismodifiedtoraise(orfireoff)an
OverDrafteventwhenevertheassignedvalueislessthan0.TheMainmethodhooksup
anothermethodthatwillrunwheneverthateventoccurs.I’llexplaintheeventfirstand
thenfollowupwithadiscussionofhowtohookupamethodthatlistensforwhenthe
eventisraisedandreceivesthemessagesentbytheevent.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
classProgram
{
privatedecimalaccountBalance=100m;
staticvoidMain(string[]args)
92 MicrosoftVisualStudio2010:ABeginner’sGuide
{
Programaccount=newProgram();
account.OverDraft+=newEventHandler(account_OverDraft);
account.CurrentBalance=-1;
Console.ReadKey();
}
publicdecimalCurrentBalance
{
get
{
returnaccountBalance;
}
set
{
if(value<0)
{
if(OverDraft!=null)
{
OverDraft(this,EventArgs.Empty);
}
}
accountBalance=value;
}
}
staticvoidaccount_OverDraft(objectsender,EventArgse)
{
Console.WriteLine("OverdraftOccurred");
}
publiceventEventHandlerOverDraft;
}
}
VB:
ModuleModule1
PrivateDimaccountBalanceAsDecimal=100
SubMain()
AddHandlerOverDraft,AddressOfAccountOverdraft
CurrentBalance=-1
Chapter4: LearningJustEnoughC#andVB.NET:IntermediateSyntax 93
Console.ReadKey()
EndSub
PublicEventOverDraftAsEventHandler
PublicSubAccountOverdraft(ByValsenderAsObject,ByValeAs
EventArgs)
Console.WriteLine("OverdraftOccurred")
EndSub
EndModule
Listing4-1hasaneventnamedOverDraft.TheOverDrafteventispublicandis
declaredwiththeeventkeyword.TheEventHandlerisadelegate,whichwe’lldiscuss
soon,butitbasicallyallowsyoutodefinethetypeofmethodthatcanbecalledbythe
event.Itdefinesthecommunicationcontractthatmustbeadheredtobyanycodethat
wishestolistenfortheeventtofire.
LookatthesetaccessoroftheCurrentBalanceproperty,insideoftheifstatement
whereitdeterminesifvalueislessthan0.TheC#examplehasanotherifstatementtosee
iftheOverDrafteventisequaltonull.
InC#whenaneventisequaltonull,itmeansthatnothinghassubscribedtobe
notifiedbytheevent—inessence,noothercodeislistening.However,whentheC#
eventisnotnull,thenthisindicatesthatsomecodesomewherehashookedupamethod
tobecalledwhentheeventfires.Thatmethodissaidtobelisteningfortheevent.So,
assumingthatthecallerhashookedupamethod,theOverDrafteventisfired.Thischeck
fornullisimportant.Ifnothingislisteningfortheevent(andourcodeknowsthistobe
thecasewhentheeventisnull),andweraiseorfiretheeventbycallingOverDraft(this,
EventArgs.Empty),anerror(nullreferenceexception)wouldoccuratruntimewhenever
avalueissetintotheCurrentBalanceproperty.TheargumentstotheC#eventmeanthat
thecurrentobject(whichistheProgramclassinstance),this,andanemptyEventArgswill
bepassedastheeventmessagetoanyothermethodsthatwerehookeduptothisevent.It
isinterestingtonotethatmanymethodscanbehookeduptoyourevent(ornoneatall),
andeachwillbenotifiedinturnwhenyoureventfires.Youshouldstarttoseethatevents
reallyareaformofalmostspontaneouscommunicationwithinyourprogram.
InVB,youdon’tneedtocheckforNothing(equivalenttoC#null).
Theprecedingdiscussiontalkedaboutamethodthatishookeduptotheeventand
executes(receivesamessage)whenevertheeventfires.Thenextsectionexplainshowto
useadelegatetospecifywhatthismethodis.
94 MicrosoftVisualStudio2010:ABeginner’sGuide
Delegates
Delegatesletyouhookupmethodsasthereceivertospecificevents.Thedelegatespecifies
theallowablesignature,thenumberofarguments,andtheirtypes,ofamethodthatis
allowedtobehookeduptotheeventasalistenerorhandler.TheEventHandlerdelegate
typefortheOverDrafteventspecifieswhatthesignatureofamethodshouldbe,asfollows:
C#:
publiceventEventHandlerOverDraft;
VB:
PublicEventOverDraftAsEventHandler
ThisEventHandlerisaclassthatbelongstothe.NETFrameworkclasslibrary,andit,
bydefinition,specifiesthatanymethodshookeduptotheOverDrafteventmustdefine
twoparameters:anobjectofanytypeandanEventArgsclass.EventHandleralsospecifies
thatthemethoddoesnotreturnavalueexplicitly.Thefollowingmethod,account_
OverDraft(AccountOverdraftinVB),matchesthepredefinedEventHandlersignature:
C#:
staticvoidaccount_OverDraft(objectsender,EventArgse)
{
Console.WriteLine("OverdraftOccurred");
}
VB:
PublicSubAccountOverdraft(ByValsenderAsObject,ByValeAs
EventArgs)
Console.WriteLine("OverdraftOccurred")
EndSub
NoticethattheC#account_OverDraft(AccountOverdraftinVB)doesn’treturn
avalueandhastwoparametersthataretypeobjectandEventArgs,respectively.The
account_OverDraft(AccountOverdraftinVB)methodishookeduptotheOverDraft
eventintheMainmethodinListing4-1,repeatedasfollowsforyourconvenience:
C#:
account.OverDraft+=newEventHandler(account_OverDraft);
account.CurrentBalance=-1;
VB:
AddHandlerOverDraft,AddressOfAccountOverdraft
CurrentBalance=-1
Chapter4: LearningJustEnoughC#andVB.NET:IntermediateSyntax 95
IntheC#example,the+=syntaxisforassigningadelegatetoanevent(usingabitof
programmerslang,thissyntaxiscommonlysaidto“wireupanevent”).TheVBexample
usesAddHandlerandAddressOftoassigntheAccountOverDraftmethodtotheOverDraft
event.IntheC#example,thedelegateisanewinstanceofEventHandlerandtheevent
isOverDraft.Ifyouremember,thedelegatetypeofOverDraftisEventhandler,which
definestheprecisemessagecontract.
Thenextpieceofthepuzzleisthemethodtobenotifiedwhentheeventhappens.
ThismethodistheparametergiventothenewEventHandlerdelegateinstance.You
sawearlierwheretheaccount_OverDraft(AccountOverDraftinVB)methodhadthe
signaturespecifiedbytheEventHandlerclass,makingitpossibleforourmethodtobe
specifiedasthenewEventHandlerparameter.Withthatonelineofcode(theonewith
the+=statement),account_OverDraft(AccountOverdraftinVB)isnowhookeduptothe
OverDraftevent.ThismeansthatwhenthevalueofCurrentBalanceissettolessthan
zeroviathesetaccessorofCurrentBalance,theOverDrafteventgetsfiredbecausethe
OverDraft(this,EventArgs.Empty)iscalled,whichtheninvokestheaccount_OverDraft
(AccountOverdraftinVB)method(themethodwewireduptotheevent),whichinturn
executesitscode.
Onemorenoteaboutevents:you’llseethemusedextensivelyingraphicaluser
interface(GUI)code.ThinkabouttheGUIcodethathasreusablecomponents,like
buttonsandlistboxes.Everytimetheuserclicksabuttonorselectsaniteminthelistbox,
youwantcodetoexecuteanddosomething,likeperhapssavetheuser’sdatasomewhere.
Youdothisthroughevents:aClickeventforthebuttonandaSelectedItemChangedfor
thelistbox.ThisisthestandardwaythatyouprogramGUIs;youhaveaneventandyou
defineamethodtohookuptothateventsothatyourrunningprogramcandosomework
inreactiontotheuser.
Asyoucansee,theEditorpopsupatooltipinstructingyoutotypeTABtocreateanew
delegateinstance.TypeTABandCodeCompletionwillpopupanothertooltipforcreating
thehandlermethod,asshowninFigure4-2.
InFigure4-2,youcanseethatCodeCompletionissuggestingamethodnameforyou.
YouhaveachoiceofpressingTABorchangingthemethodnameandthenpressingTAB.
Eitherway,youhaveafastwaytohookupahandlermethodtoaneventviatheevent’s
delegatetype.
Justasadelegateprovidesaninterfacetoamethodthatisacontractbasicallyto
describehowtocommunicate,youcanalsodefineinterfacestoclassestocommunicate
withtheminaspecifiedway,andtheseareintuitivelynamed...interfaces.
Implementing Interfaces
Anotherlanguagefeaturethatgivesyouflexibilityisinterfaces.Aninterfacecanbeuseful
ifyouwanttohaveagroupofclassesthatcanbeinterchangedatanytime,yetyouneed
towritethesameoperationsforeachoftheseclasses.Essentially,youwanttowritethe
codethatusestheclassonlyonetime,butstillswitchwhattheactualclassis.That’swhere
interfacescomein.Theinterfacecreatesacontractthateachoftheinterchangeableclasses
mustadhereto.So,iftheinterfacesaysthatallclassesthatimplementtheinterfacehave
methodAandpropertyB,theneveryclassthatimplementstheinterfacemusthavemethod
AandpropertyB;thecompilerenforcesthislikeacontractthatcannotbebroken.The
followingsectionsshowyouhowtowriteaninterfaceandthenbuildacoupleofclasses
thatimplementthatinterface.Finally,you’llseehowtowritecodeagainsttheinterface.
Oneimportantfacttorememberaboutinterfacesisthattheydon’thaveanycodeother
thandefinitionsofmembers.Thisdefinitionofmembersisthecontractoftheinterface.
Youaretheonewhomusttowriteaclassthatcontainsthemembersoftheinterface,and
youmustwritethecodethatprovidesanimplementationoftheinterfacemembers.A
commonpointofconfusionisthataninterfacedoesnothaveanyexecutablecode,butthe
classesthatimplementtheinterfacesdo.
Thefollowingsectionsshowyouhowtocreateaninterface,howtocreateaclassthat
hascode(thatyou’vewritten)toimplementtheinterfacecontract,andhowtowritecode
thatoperatesontheclassesthatimplement(guaranteethecontractof)theinterface.
Chapter4: LearningJustEnoughC#andVB.NET:IntermediateSyntax 97
Creating an Interface
Tocreateaninterface,right-clicktheprojectinSolutionExplorer,selectAdd|NewItem,
selectCodeunderthelanguagebranchinInstalledTemplates,andselecttheInterfaceitem.
NametheInterfaceIAccountandclickAdd.Bystandardconvention,youwillalways
nameanyinterfaceclassyoucreatewithanamethatstartswithanuppercaseletterI.You’ll
seetheinterfaceinListing4-2addedtoyourproject:
Listing4-2 An interface
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
publicinterfaceIAccount
{
voidCredit(decimalamount);
voidDebit(decimalamount);
decimalCurrentBalance{get;set;}
}
}
VB:
PublicInterfaceIAccount
SubCredit(ByValamountAsDecimal)
SubDebit(ByValamountAsDecimal)
PropertyCurrentBalanceAsDecimal
EndInterface
Afteryou’veaddedtheinterface,you’llneedtomakemodificationstomakethecode
matchListing4-2.NoticethattheIAccountmembersdon’thaveanimplementationand
soappearincompletebecausetheyhavenolinesofcode.Also,eachmemberdoesn’thave
apublicmodifier,becauseinterfacemembersareimplicitlypublic.Thefollowingsections
showyouhowtobuildtheclassesthatimplementtheIAccountinterface;there,you
shouldbegintoseethebenefitthataninterfacecanbring.
98 MicrosoftVisualStudio2010:ABeginner’sGuide
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
classChecking:IAccount
{
publicvoidCredit(decimalamount)
{
//implementcheckinglogic
CurrentBalance+=amount;
Console.Writeline("Added"+amount.ToString()+
"toCheckingAccount");
}
publicvoidDebit(decimalamount)
{
//implementcheckinglogic
CurrentBalance-=amount;
Console.Writeline("Debited"+amount.ToString()+
"fromCheckingAccount");
}
publicdecimalCurrentBalance{get;set;}
}
}
VB:
PublicClassChecking
ImplementsIAccount
PublicSubCredit(ByValamountAsDecimal)ImplementsIAccount.
Credit
Chapter4: LearningJustEnoughC#andVB.NET:IntermediateSyntax 99
'ImplementCheckinglogic
CurrentBalance+=amount
Console.Writeline("Added"&amount.ToString()&
"toCheckingAccount")
EndSub
PublicSubDebit(ByValamountAsDecimal)ImplementsIAccount.Debit
'ImplementCheckinglogic
CurrentBalance-=amount
Console.Writeline("Debited"+amount.ToString()+
"fromCheckingAccount")
EndSub
PublicPropertyCurrentBalanceAsDecimalImplementsIAccount.
CurrentBalance
EndClass
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceFirstProgram
{
classSaving:IAccount
{
publicvoidCredit(decimalamount)
{
//implementsavingslogic
CurrentBalance+=amount;
Console.Writeline("Added"+amount.ToString()+
"toSavingAccount");
}
publicvoidDebit(decimalamount)
{
//implementsavingslogic
CurrentBalance-=amount;
Console.Writeline("Debited"+amount.ToString()+
"fromSavingAccount");
}
100 MicrosoftVisualStudio2010:ABeginner’sGuide
publicdecimalCurrentBalance{get;set;}
}
}
VB:
PublicClassSaving
ImplementsIAccount
PublicSubCredit(ByValamountAsDecimal)ImplementsIAccount.
Credit
'ImplementSavinglogic
CurrentBalance+=amount
Console.Writeline("Added"&amount.ToString()&
"toSavingAccount")
EndSub
PublicSubDebit(ByValamountAsDecimal)ImplementsIAccount.Debit
'ImplementSavinglogic
CurrentBalance-=amount
Console.Writeline("Debited"+amount.ToString()+
"fromSavingAccount")
EndSub
PublicPropertyCurrentBalanceAsDecimal
ImplementsIAccount.CurrentBalance
EndClass
InbothListings4-3and4-4,noticethattheCheckingandSaving,respectively,
implementtheIAccountinterface,repeatedasfollows:
C#:
classChecking:IAccount
and
classSaving:IAccount
VB:
PublicClassChecking
ImplementsIAccount
and
PublicClassSaving
ImplementsIAccount
Chapter4: LearningJustEnoughC#andVB.NET:IntermediateSyntax 101
IntheC#listing,followingtheclassnamebyacolonandthentheinterfacename
specifiesthattheclasswillimplementtheinterface.TheVBlistingusestheImplements
keywordtoindicatethatCheckingandSavingclassesimplementtheIAccountinterface.
LookingatbothCheckingandSaving,youcanseethattheyhavetheCredit,Debit,and
CurrentBalancemembersthatarespecifiedinIAccount.Theprimarydifferenceisthat
IAccountdoesn’thaveanimplementation,butyouwroteanimplementationforChecking
andSaving.Listings4-3and4-4simplifytheimplementationoftheinterfacesothatyou
don’thavetoreadalotofcodethatdoesn’taddtothepurposeofthelistingtoshowyou
howaclassimplementsaninterface.Inreality,thecodeinthemethodswouldbedifferent
forCheckingandSavingbecausetheyaredifferentaccounttypeswithdifferentbusiness
rules.
You’vecreatedaninterfaceandwrittenclassestoimplementthecontractofthat
interface.Thenextsectiongivesyouacoupleofexamplestohelpclarifythepracticaluse
ofinterfaces.
Listing4-5 Processing payroll with explicit checking and saving class instances
C#:
publicvoidProcessPayrollForCheckingAndSavingAccounts()
{
Checking[]checkAccounts=GetCheckingAccounts();
foreach(varcheckAcctincheckAccounts)
{
checkAcct.Credit(500);
}
102 MicrosoftVisualStudio2010:ABeginner’sGuide
Saving[]savingAccounts=GetSavingAccounts();
foreach(varsavingAcctinsavingAccounts)
{
savingAcct.Credit(500);
}
}
publicChecking[]GetCheckingAccounts()
{
Checking[]chkAccts=newChecking[2];
chkAccts[0]=newChecking();
chkAccts[1]=newChecking();
returnchkAccts;
}
publicSaving[]GetSavingAccounts()
{
intnumberOfAccounts=5;
Saving[]savAccts=newSaving[numberOfAccounts];
for(inti=0;i<numberOfAccounts;i++)
{
savAccts[i]=newSaving();
}
returnsavAccts;
}
VB:
SubProcessPayrollForCheckingAndSavingAccounts()
DimcheckAccountsAsChecking()=GetCheckingAccounts()
ForEachcheckAcctIncheckAccounts
checkAcct.Credit(500)
Next
DimsavingAccountsAsSaving()=GetSavingsAccounts()
ForEachsavingAcctInsavingAccounts
savingAcct.Credit(500)
Next
EndSub
Chapter4: LearningJustEnoughC#andVB.NET:IntermediateSyntax 103
FunctionGetCheckingAccounts()AsChecking()
DimchkAccts(1)AsChecking
chkAccts(0)=NewChecking()
chkAccts(1)=NewChecking()
ReturnchkAccts
EndFunction
FunctionGetSavingsAccounts()AsSaving()
DimnumberOfAccountsAsInteger=5
DimsavAccts(numberOfAccounts)AsSaving
ForiAsInteger=0TonumberOfAccounts
savAccts(i)=NewSaving()
Next
ReturnsavAccts
EndFunction
Tosavespace,Ihaven’tincludedtheentireapplicationinListing4-5,whichis
availablewiththesourcecodeforthisbookviatheMcGraw-HillWebsite.Tounderstand
howitworks,imaginethatyou’vewrittenthefollowingcodeintheMainmethod:
C#:
Programbank=newProgram();
bank.ProcessPayrollForCheckingAndSavingAccounts();
VB:
ProcessPayrollForCheckingAndSavingAccounts()
Walkingthroughthecode,let’sstartattheProcessPayrollForCheckingAndSaving
Accountsmethod.YoucanseehowthealgorithmcallsGetCheckingAccountstoretrieve
anarrayofCheckingobjects.Ifyourecall,anarrayisalistofelementsofaspecified
type,thattypebeingCheckinginthiscase.Thealgorithmgoesontoiteratethroughthe
Checkingobjects,invokingCreditoneachtoadd500totheaccount.Someemployees
wanttheirpaychecksinChecking,butothersmightwanttheirpaycheckstogointo
Saving(orsomeotheraccount).Therefore,thealgorithmcallsGetSavingsAccountsto
getalistofthoseaccountsforemployeeswhowanttheirpaycheckstogointotheir
savings.You’llnoticethatthealgorithminsideofGetSavingsAccountsisdifferentfrom
104 MicrosoftVisualStudio2010:ABeginner’sGuide
GetCheckingAccounts,whichIdidonpurposesothatyou’llseedifferentwaystouse
loops;butthisdoesn’taffectthecallingcodebecauseit’sencapsulatedinindividual
methods.ThepointtomakehereisthatGetCheckingAccountswillonlyreturnChecking
classinstancesandGetSavingsAccountswillonlyreturnSavingclassinstances.Therest
ofthealgorithmintheProcessPayrollForCheckingAndSavingAccountsmethodmirrorsthe
processingforChecking.
WhatshouldcatchyourattentionistheduplicationofcodeintheProcessPayroll
ForCheckingAndSavingAccountsmethod.AlthoughtheCreditmethodsofCheckingand
Savingshouldhavedifferentimplementations,thecodecallingCreditcanbethesame,
eliminatingduplication.Listing4-6showshowtotakeadvantageofthefactthatboth
CheckingandSavingimplementthesameinterface,IAccount.You’llseehowtocall
CreditonanyIAccount-derivedtypewithonealgorithm,eliminatingtheduplicationyou
sawinListing4-5.
C#:
publicvoidProcessPayrollForAllAccounts()
{
IAccount[]accounts=GetAllAccounts();
foreach(varaccountinaccounts)
{
account.Credit(1000);
}
}
publicIAccount[]GetAllAccounts()
{
IAccount[]allAccounts=newIAccount[4];
allAccounts[0]=newChecking();
allAccounts[1]=newSaving();
allAccounts[2]=newChecking();
allAccounts[3]=newSaving();
returnallAccounts;
}
Chapter4: LearningJustEnoughC#andVB.NET:IntermediateSyntax 105
VB:
SubProcessPayrollForAllAccounts()
DimaccountsAsIAccount()=GetAllAccounts()
ForEachaccountInaccounts
account.Credit(1000)
Next
EndSub
FunctionGetAllAccounts()AsIAccount()
DimallAccounts(3)AsIAccount
allAccounts(0)=NewChecking()
allAccounts(1)=NewSaving()
allAccounts(2)=NewChecking()
allAccounts(3)=NewSaving()
ReturnallAccounts
EndFunction
YoucancallthecodeinListing4-6fromtheMainmethodlikethis:
C#:
Programbank=newProgram();
bank.ProcessPayrollForAllAccounts();
VB:
ProcessPayrollForAllAccounts()
ExaminingListing4-6,youcanseethataccountsisanarrayofIAccount.While
youcan’tinstantiateaninterfacebyitself,youcanassignaninstanceoftheclassthat
implementsthatinterfaceusingavariablesimplydeclaredastheinterfacetype.Inthis
case,GetAllAccountsreturnsalistofobjectsthatimplementIAccount.
LookinginsideoftheGetAllAccountsmethod,youcanseehowanarrayisbeingbuilt
withbothCheckingandSavingobjects.SinceCheckingandSavingimplementIAccount,
whichyousawinListings4-3and4-4,instancesofCheckingandSavingcanbedirectly
assignedintoelementsofanIAccountarray.
BackintheProcessPayrollForAllAccountsmethod,youcanseealoopiteratethrough
eachIAccountinstance,callingCredit.ThereasonyoucancallCreditlikethisisthat
IAccountdefinesacontractfortheCreditmethod.CallingCreditoneachinstancereally
106 MicrosoftVisualStudio2010:ABeginner’sGuide
invokestheCreditmethodontheruntimeCheckingorSavinginstance.Yourcodethat
youwroteforChecking.CreditandSaving.Creditwillexecuteasifyourcodecalledthem
directlyasinListing4-5.Alsoobservethatwe’veeliminatedtheduplicationbecauseone
algorithm,namelyIAccount.Credit()inourexample,worksonbothCheckingandSaving
objects.
Nowyoucanseethatinterfaceshelpyoutreatdifferenttypesofobjectsasiftheywere
thesametypeandhelpsyousimplifythecodeyouneedtowritewheninteractingwith
thoseobjects,eliminatingduplication.Imaginewhatwouldhappenifyouweretasked
withaddingmorebankaccounttypestothisalgorithmwithoutinterfaces;youwouldneed
togointothealgorithmtowriteduplicatecodeforeachaccounttype.However,nowyou
cancreatethenewaccounttypesandderivethemfromIAccount;thenewaccounttypes
automaticallyworkinthesamealgorithm.
Coding Arrays
You’vealreadyseenseveralexamplesofarraysbeingusedpreviouslyinthischapter.You
declareavariableofthearraytype,instantiatethearraytoaspecifiedsize,andthenuse
thearraybyindexingintoitselements.Listing4-7showsanexamplethatdemonstrates
themechanicsofcreatingandusinganarray.
C#:
privatevoidArrayDemo()
{
double[]stats=newdouble[3];
stats[0]=1.1;
stats[1]=2.2;
stats[2]=3.3;
doublesum=0;
for(inti=0;i<stats.Length;i++)
{
sum+=stats[i];
}
Console.WriteLine(
stats[0]+"+"+
stats[1]+"+"+
stats[2]+"="+
sum);
}
108 MicrosoftVisualStudio2010:ABeginner’sGuide
VB:
SubArrayDemo()
Dimstats(2)AsDouble
stats(0)=1.1
stats(1)=2.2
stats(2)=3.3
DimsumAsDouble=0
ForiAsInteger=0To2
sum+=stats(i)
Next
Console.WriteLine(
stats(0)&"+"&
stats(1)&"+"&
stats(2)&"="&
sum)
EndSub
IntheC#exampleofListing4-7,youcanseethatthestatsvariableisdeclaredas
double[],anarrayoftypedouble.Youmustinstantiatearrays,asisdonebyassigningnew
double[3]tostats,where3isthenumberofelementsinthearray.C#arraysareaccessed
viaa0-basedindex,meaningthatstatshasthreeelementswithindexes0,1,and2.
TheVBexampledeclaresstatsasanarrayoftypedouble.Noticethattherankofthe
arrayis2,meaningthat2isthehighestindexinthearray.Sincethearrayis0-based,stats
containsindexes0,1,and2;threeelementstotal.
Assigningvaluestoanarraymeansthatyouusethenameofthearrayandspecifythe
indexoftheelementyouwanttoassignavalueto.Forexample,stats[0](stats(0)inVB)
isthefirstelementofthestatsarray,andyoucanseefromthelistinghoweachelement
ofthestatsarrayisassignedthevalues1.1,2.2,and3.3.Theforloopaddseachelement
ofthearraytothesumvariable.Finally,youcanseehowtoreadvaluesfromanarrayby
examiningtheargumenttotheConsole.WriteLinestatement.Usingtheelementaccess
syntax,youcanseehowtoreadaspecificelementfromthestatsarray.
Anarrayisafixed-sizecollection,andthereforesomewhatlimitedinfunctionality.
Inpractice,you’llwanttousemoresophisticatedcollections,liketheListclass,whichis
referredtoasagenericcollection.Notallcollectionclassesinthe.NETFrameworkare
genericcollections;however,genericcollectionsarenowthepreferredkindofcollection
touseinmostcases.
Chapter4: LearningJustEnoughC#andVB.NET:IntermediateSyntax 109
Coding Generics
Genericsarelanguagefeaturesthatallowyoutowriteapieceofcodethatwillworkwith
multipletypesefficiently.Agenericclassdefinitionhasaplaceholderforthetypeyou
wantittorepresent,andyouusethisplaceholdertodeclarethetypeyouwanttowork
with.Thereisanentirelibraryofgenericcollectionsin.NETaswellasgenerictypes
acrosstheentire.NETFrameworkClasslibrary.Becauseofthevolumeofinformation
requiredforcomprehensivecoverageofgenerics,thissectionwillonlyserveasabrief
introduction,givingyouanexampleofgenericusethatyou’remostlikelytoseeinthe
future.Listing4-8demonstrateshowtodeclareagenericList.Thecodespecifiesthe
typeofthelistasaCheckingaccountandthenproceedstopopulatethegenericlistand
performoperationsontheCheckingelementsofthegenericlist.Remembertoincludea
usingdirective(importsforVB)fortheSystem.Collections.Genericnamespacenearthe
topwithinyourfile.
C#:
privatevoidListDemo()
{
List<Checking>checkAccts=newList<Checking>();
checkAccts.Add(newChecking());
checkAccts.Add(newChecking());
for(inti=0;i<checkAccts.Count;i++)
{
Console.WriteLine(checkAccts[i].CurrentBalance);
}
}
VB:
SubListDemo()
DimcheckAcctsAsNewList(OfChecking)
checkAccts.Add(NewChecking())
checkAccts.Add(NewChecking())
ForiAsInteger=0TocheckAccts.Count-1
Console.WriteLine(checkAccts(i).CurrentBalance)
Next
EndSub
110 MicrosoftVisualStudio2010:ABeginner’sGuide
In.NET,thegenericListtypeisdeclaredasList<T>,orList(OfT)inVB.TheTisa
typeplaceholder,whereyoucanspecifyanytypeyouwant.Forexample,youcouldcreate
aList<int>forintegersoraList<string>forstrings,whichwouldbeList(OfInteger)
andList(OfString)inVB,respectively.InListing4-8,youcanseethatcheckAcctsis
declaredasList<Checking>(List(OfChecking)inVB).Sincealistgrowsdynamically
toaccommodateanynumberofelements,youusetheAddmethodtoaddelementstothe
List.OnceelementsareintheList,youcanuseelementaccesssyntax,asshowninthefor
loop,toaccesstheelementsoneatatime.CollectionssuchasListareconvenientbecause
theyhavemultipleconveniencemethods,suchasClear,Contains,Remove,andmore.
InadditiontoList,theSystem.Collections.Genericnamespacehasseveralother
genericcollections,suchasDictionary,Queue,andStack.Eachgenericisinitializedby
replacingthetypeparameterswiththetypesyouwanttoworkonandthenbyusingthe
specializedmethodsofthatcollection.Wheneveryouseethetypeparametersyntax,you
shouldrecognizethatagenericisbeingusedandyouwillhaveanideaofwhatthecode
meansandhowtoreaditinthedocumentation.
Summary
Whatyoulearnedinthischapterwereessentialskillsforupcomingchaptersinthe
restofthebook.Knowinghowdelegatesandeventsworkhelpsyouwithevent-driven
developmentthatiscommontoGUIapplicationdevelopment.Understandinginterfaces
directlyrelatestobeingabletobuildWebservices,amongotheruses.You’llalsomake
regularusageofarraysandgenerics,andthischaptergaveyoutheessentialstoknow
whatcollectionsare.
RememberthatthiswasonlyanintroductiontoC#andVBandthatthereismuch
moretolearnabouttheselanguages.Ofcourse,thisbookisaboutVSandnotlanguages,
sothenextchapteriswhereyou’lllearntobuildVSprojects.
Part II
Learning the VS 2010
Environment
This page intentionally left blank
Chapter
Creating and
5
Building Projects
113
114 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● WorkwithProjectsandSolutions
● SetPropertiesinthePropertiesWindow
● ReferenceandUseClassLibraries
● CompileandRunProjects
● UsetheClassDesigner
P rojectsandsolutionsareVS’swayofhelpingyouorganizeyourcodeforboth
developmentanddeployment.Fordevelopment,youhaveahierarchicalstructurethatis
flexibleandallowsyoutoorganizeyourcodeinawaythatmakessenseforyouandyour
team.Fordeployment,youcanbuilddifferentprojecttypesthatwillresultinexecutableor
libraryfiles(oftenreferredtoasassemblies)thatrunyourprogramwhenexecuted.
Whilereadingthischapter,you’lllearnhowtousesolutionsandprojects.You’lllearn
howtofindsettingsandoptionsforcustomizingprojects,howtoreferenceassemblies,
anddifferentoptionsforcompilingcode.Asanextrabonus,you’lllearnhowtheClass
Designerallowsyoutoobtainahigh-levelvisualizationofyourcodeandperformsome
designwork.We’llbeginwithlearningaboutsolutionsandprojects.
aprojectinsideofasolution.Differentprojecttypeshaveuniquesettingsandoptions,but
we’llstartbycreatingaConsoleapplication,whichwillreduceunnecessarydetailand
helpfocusonthecommonfeaturesofallprojecttypes.
VSwillupdatetheSolutionNamewiththesamename.Inamultiprojectsolution,this
mightnotmakesense.So,firsttypetheprojectnameandthenyoucanprovideanamefor
thesolutionthatismoreappropriate.InFigure5-1,youcanseethattheprojectisnamed
ProjectDemoandthesolutionisnamedSolutionDemo.VSallowsyoutoputspacesin
thenames.Aconsequenceofthisisthatthedefaultnamespaceforaprojectwillusethe
projectnamewithspacestranslatedtounderlines;somethingtobeawareofifyourcoding
conventionsdon’tallowunderlinesinidentifiernames.
Ifyouhaveaverysimpleprojectandwantallprojectfilesinthesamefolder,uncheck
CreateDirectoryForSolution.However,mostapplicationsyoubuildwillhavemultiple
projectsandleavingthisboxcheckedmakesmoresensebecauseitmaintainsconsistency
betweenfolderandsolutionorganization.Inanycase,whenanadditionalprojectisadded
toyoursolution,VSwillalwaysputthenewprojectintoaseparatesubfolder.
IfyoucheckAddToSourceControl,VSwillopenawindowforyoutoconfiguresource
control.Sourcecontrolisarepositoryforyoutocheckcodeinto.Thisisespeciallyuseful
forteamswhereeachdevelopercancheckinhisorhercodeforacommonrepositoryof
sourcecodeforthissolutionwhenyoucreatethesolution.ClickOKtocreatethesolution.
TIP
If you accidentally start a project type that you didn’t intend, select File | Close Solution
and then delete the solution folders from the file system. VS will often put OS locks on files,
so it’s important to close the solution so that you will be able to delete files. The VS Recent
Projects list will have an entry with the name of the solution you just deleted, but you can
click that entry and VS will recognize that the solution no longer exists, prompting you
to remove the entry from the list. After that, you can start over again and use the same
solution/project name you intended, but with the right project type.
StartinganewConsoleprojectinVB,youonlyneedtoprovideaNameparameter,
whichisthenameoftheprojecttocreate.Oncetheprojectiscreated,thefirsttimeyou
createtheproject,you’llreceiveawindowthatasksyouforName,SolutionName,
Location,CreateDirectory,andAddToSourceControloptionsthatworkthesameas
describedforthepreviousC#example.You’veaccomplishedthesametask,regardlessof
language,butindifferentways.
changethisbyselectingTools|Options|ProjectsAndSolutionsandcheckingtheboxfor
AlwaysShowSolution.
Youcanaddmultipleprojectstoasolution,aswellasfoldersfororganizingthe
projects.Right-clickthesolutionnameintheSolutionExplorerandselectAdd|New
Project,andyoucanaddmoreprojects.Add|ExistingProjectallowsyoutoaddaproject
thatalreadyexiststoyouropenedsolution.ThereasonthisoptionexistsisthatwhileVS
solutionsassociateoneormoreprojectstogetherasasolutionunit,anysingleproject
couldoptionallybeassociatedwithothersolutions.Inotherwords,asingleprojectcould
besharedwithothersolutions.
SelectAdd|NewSolutionFoldertoaddafoldertoasolution.Youcanaddahierarchy
offolderstoasolutionfororganizingprojects.Onethingtorememberaboutsolutionfolders
isthatunlikecreatingfoldersinsideaprojectthatbecomephysicalfilesystemfolders,
solutionfoldersarelogicalanddon’tcreateaphysicalfolderinyourfilesystem.Ifyouwant
yourfilesystemlayouttomatchtheSolutionExplorerlayoutwithsolutionfolders,you
mustcreatethefilesystemfoldersyourself.Toavoidconfusion,rememberthatitispossible
forthephysicallocationofprojectstodifferfromtheSolutionExplorerlayout.
Besidesorganizingprojects,solutionfoldersarealsousefulforassociatingspecific
artifactswithyourproject.Whilesolutionfoldersarenottiedtophysicalfilesystem
folders,theyareincludedwithsourcecontrolproviders,suchasVisualSourceSafeand
TeamSystem.Onepotentialuseofasolutionfolderistoincludeacopyofanexternalclass
librarythatyou’vebuiltyourprojectwith.Thisway,wheneverothermembersoftheteam
checkthesolutionoutofsourcecontrol,theyallareworkingwiththesamefilesandversions.
Solutionfolderscanalsobeusedforanytypeoffile,includingprojectdocumentationor
anythingelsethatyouwanttokeeporganizedinasingleplace.
Dependingonprojecttype,VShidesvariousfilesassociatedwithaproject.TheSolution
ExplorertoolbarhasaShowAllFilesbuttonthatwillshowthesehiddenfiles.Ifyouhavethe
118 MicrosoftVisualStudio2010:ABeginner’sGuide
solutionselected,allyou’llseeistheAddANewSolutionFolderbutton,soyou’llneedto
selectaprojectbeforetheShowAllFilesbuttonwilldisplay.Anexampleofahiddenfileis
thebinfolderhierarchythatcontainstheoutputofyourprojectwhenyoucompile.
toallprojects.ThefollowingsectionsdescribeeachofthefeaturesoftheApplication
settingstab.
Assembly Name
VSprojectscreateeither*.dllor*.exeassemblies.Theassemblynameprovidesthe
filenameforthisprojectanddefaultstothenameofyourproject.FromFigure5-3,you
canseethatAssemblyNameissettoProjectDemo.SincethisisaConsoleapplication,
theoutputwouldbea*.exe.ItfollowsthatthefilenamewouldbeProjectDemo.exe.Had
theprojecttypebeenaClassLibrary,thefilenamewouldhavebeenProjectDemo.dll.
Default Namespace
TheDefaultnamespace(RootnamespaceinVB)settingdetermineswhatthenamespace
willbedefinedautomaticallyaswheneveryouaddanewcodefiletoyourproject.It’s
initiallysettothenameofyourproject.Ifyouwantthenamespaceofnewfilestobe
different,setthenamespacehere.
Target Framework
VShas.NETFrameworkmultitargetingsupport,whereyoucanworkwithanyversionof
.NETbetweenv2.0andv4.0.Selectthe.NETversionyouneedintheTargetFramework
combobox.VBincludesthisoptionontheCompiletabwhenclickingtheAdvanced
CompileOptionsbutton.RemembertosettheVBprojectfrom.NETFramework4.0
ClientProfileto.NETFramework4.0becauselaterwe’llbereferencingaclasslibrary
thatissetto.NETFramework4.0andthetargetframeworksmustbecompatibleforone
assemblytoreferenceanother.
Sinceyoucanhavemultipleversionsof.NETonthesamemachineasVS2010,
youcanswitchfreelybetweendifferentprojectsthatusedifferent.NETversions.This
isparticularlyusefulifyou’reaconsultantworkingondifferentprojectswithdifferent
versionsorifyou’reprovidingmaintenancesupportonolderversionsofaproductwhile
doingactivedevelopmentworkinadifferentprojectusing.NET4.0.
Output Type
AnOutputtype(ApplicationtypeinVB)isthetypeofassemblycreatedwhenyoubuild
yourproject.ThethreetypesofoutputareWindowsApplication,ConsoleApplication,
andClassLibrary.YoualreadyknowhowtocreateaConsoleapplication,whichproduces
a*.exeassembly.Laterinthischapter,you’lllearnhowtocreateaClassLibraryproject,
whichproducesa*.dllassembly.InChapter8,you’lllearnhowtocreateaWindows
Applicationproject,whichisa*.exe.
120 MicrosoftVisualStudio2010:ABeginner’sGuide
TIP
If you have a WPF project, its Output Type is set to Windows Application. If you
switched the Output Type of a WPF application to Console Application, you would see
the Console window appear also. This might be useful for some intermediate debugging
where you could emit Console.WriteLine messages. Of course, VS provides excellent
debugging tools, which you’ll learn about in Chapter 6, including an Output window,
but this is just another option if you ever wanted it.
Startup Object
YoucouldaddmultipleMainmethodstoaConsoleapplicationoraWPFapplication,
butonlyoneMainmethodcanbeactiveatatime.TheStartupobjectallowsyouto
specifywhichclasscontainstheMainmethodyouwanttouseastheentrypointtoyour
application.Oneofthereasonsyoumightwanttodothisistostartyourapplicationin
differentconfigurations,whichmightfacilitatetestingbyallowingyoutogostraighttoa
partoftheprogramwithouttoomuchnavigation.
TIP
VS ships with system icons that you can use in your own applications. Navigate to C:\
Program Files\Microsoft Visual Studio 10.0\Common7\VS2010ImageLibrary\1033
and you’ll see a Zip file named VS2010ImageLibrary. Your path might be different
if you chose to install VS2010 somewhere other than the default. Unzip this
VS2010ImageLibrary and you’ll see a plethora of resources with images, audio,
animations, and icons that are common to Microsoft operating systems and applications.
ThemanifestallowsyoutospecifyMicrosoftWindowsUserAccessControl(UAC)
settingsortosupportaformofdeploymentcalledClick-Once,whereaWPFapplication
canbedeployedfromaWebpageandrunlocallyonyourdesktopmachine.Themanifest
describestheapplicationanddeploymentfeaturesofyourClick-Onceapplication.Since
thesemanifestsareautomaticallygeneratedwhenyoupublishaClick-Onceapplication,
younormallywon’tevermanuallybuildmanifestfilesyourself;thisisconsidered
anadvancedpracticeandincludesknowledgebeyondwhatabeginner’sguidewould
include.
InVB,thereisaUACSettingsbuttonthatallowsyoutodirectlymodifytheapp
.manifestfile.Thisisanadvancedtechniquethatrequiresknowledgeoftheoperating
systemUACsettings.
Chapter5: CreatingandBuildingProjects 121
IfyouselecttheResourcesoption,youcanincludeaWin32resourcesfile,which
youcanthenaccessthroughcodeinyourapplication.Thisisanotheradvancedscenario
beyondthescopeofthisbook.
Assembly Information
ClickingAssemblyInformationshowsthewindowinFigure5-4.Thisinformationis
includedintheassemblymetadatawhenyoubuildyourproject.Mostoftheinformation
inthiswindowisself-explanatory.Sinceassembliescancomprisemultiplefiles,youare
allowedtovarytheassembly(allfiles)andthisfile’sassemblyversionnumbers.
With.NET,youcanhavetwo-waycommunicationswithComponentObjectModel
(COM)applications.YoucanenablethisbyallowingyourassemblytohaveaGlobally
UniqueIdentifier(GUID)sothatCOMcanfindit,andchecktheCOMvisiblebox.
LeavetheNeutralLanguageasNone,unlessyouwantthedefaultlocalitytobe
somethingotherthanen-US,whichisthelocaleforUSEnglish.
Toseewhatthesesettingslooklike,pressF6tobuildtheapplication,andthennavigateto
thelocationinthefilesystemwhereyoucreatedtheproject.Thelocationonmymachinefor
thisdemoisC:\VS2010\Chapter05\SolutionDemo\ProjectDemo\bin\Debug,butyourscould
bedifferentifyoucreatedyourprojectinadifferentlocation.Regardless,you’llfindthe
ProjectDemo.exefileinthebin\Debugfolder.Right-clickProjectDemo.exe,selectProperties,
andclicktheDetailstaboftheProjectDemoPropertieswindow,showninFigure5-5.
AsyoucanseeinFigure5-5,theAssemblyInformationfromtheprojectproperties
isincludedwiththefile.Thisisconvenientforyou(oranenduser)tobeabletoopen
thefileandreadpertinentinformation,especiallyversioninformation,toknowyou’re
workingwiththecorrectassembly,fordebugging,orjusttoknowwhatisonyoursystem.
Referencing Assemblies
Allprojectsnormallyreferenceexternalassemblies.Forexample,System.dllisa.NET
Frameworkassemblythatcontainsalloftheprimitive.NETtypesandisnormallyincludedin
everyproject.EachprojecttypehasaspecificsetofassembliesthatappearintheReferences
list.Theassembliesthatappearinthislistareeitherrequiredbecauseofthetypeofproject
youarebuildingorareoptionalandcontainlibrariesthatarecommonlyusedforthattypeof
project.Youarefreetoremoveassemblyreferencesifyoulike,butbeawarethatremoving
areferencetoanassemblyrequiredforthatprojecttypeislikelytoresultinyourcodenot
beingabletocompile.
Chapter5: CreatingandBuildingProjects 123
Assemblyreferencesareaddedtoaprojecttotellthecompilerwheretofindthetypes
itisusinginanapplication.Whenyourcompilerruns,itwillknowwhattypesyouhave
inyourcodeandlooksthroughthesetofreferencedassembliestofindthattype.Adding
anassemblyreferencedoesn’taddallofthecodefromthereferencedassemblytoyour
code;itjusttellsthecompilerwheretolook.
NOTE
There is often confusion around the relationship between assembly references and
namespaces. A namespace using statement (Imports in VB) allows your code to be
written without fully qualifying type references for types in an assembly. However, the
assembly reference is just a way to tell the compiler in which specific external assembly
to look to find those types: two different purposes. This confusion is exacerbated by the
fact that you get the same error message from the compiler when you either are missing
an assembly reference or don’t have a using (Imports for VB) directive in your code for
a namespace that a type resides in. Just remember to ensure that you have an assembly
reference first and then add a using (Imports) directive at the top of your file.
(GAC),whichisasharedrepositoryofassemblies.Microsoftandthirdpartieswillplace
assembliesintheGACtomakeiteasiertosharethembyanyprograms.
TheCOMtabshowsalloftheCOMapplicationscurrentlyregisteredonyour
computer.Forexample,ifyouwantedtocommunicatewithExcel,youwouldclick
theCOMtabandaddareferencetotheversionofMicrosoftOfficeExcelthatyouare
workingwith.AddingareferencetoaCOMobjectcausesVStoautomaticallygenerate
anewassembly,calledanInteropassembly,thathasstubmethodsthatmakeiteasy
foryoutoperformoperationsonthatCOMobject.Youwouldneedtoreferencethe
documentationfortheCOMobject/applicationtodeterminewhatoperationsarepossible,
butthisisaverypowerfulwaytoworkwithlegacyapplicationsandMicrosoftOffice
applicationsthatexposeaCOMinterface.
CAUTION
If you’re adding an assembly reference for a VB project, remember to open My
Projects on ProjectDemo, go to the Compile tab, click the Advanced Compile Options
button, and ensure that the Target Framework is set to .NET Framework 4.0 (not
.NET Framework 4.0 Client Profile). The reason is that the class library project is
automatically set to .NET Framework 4.0 and the target framework for both the
referencing and referenced assemblies must be the same.
TheRecenttabhasalistofreferencesthatyou’verecentlyaddedtoaproject,which
isaconveniencebasedontheprobabilitythatifyouaddedareferencetooneproject
inasolution,youmightwanttoquicklyaddthatsamereferencetoothers.TheBrowse
taboftheAddReferencewindowallowsyoutosearchthefilesystemfora*.dllfileto
addasareference.Justrememberthatifyouarereferencinga*.dllforaprojectinthe
samesolution,itwouldbebettertousetheProjecttab,whichmanagesdependenciesand
ensuresthatyourprojectisupdatedifthereferencedprojectchanges.Filereferencescan’t
knowiftheexternal*.dllchangedbecausetheexternal*.dllisoutsideofyoursolution.
Inmostcases,ifyou’rereferencinganexternal*.dll,youdon’thavethecode,soaproject
referencewon’tbepossible.Thenextsectionexplainsmoreaboutprojectreferences.
NOTE
The New Projects window, CTRL-N, contains Office project types that can help you get
started building Microsoft Office applications.
openthePropertieswindowbydouble-clickingMyProject,clicktheReferencestab,
selectthereferencetodelete,andclickRemove.Figure5-7showstheVBReferencestab.
VBincludesadditionalfunctionalityontheReferencestab.Forexample,youcan
clickAddtoaddareference.YoualsoclickUnusedReferencestoremovereferencesfor
assembliesthatarenotbeingusedinyourcode.ClickingReferencePathsallowsyouto
specifyafolderthatVSwilllookintofindassembliesyouwanttoreference.
C#hasaseparatetabonthePropertieswindowformanagingReferencePaths.When
VSlooksforreferencedassemblies,itwillsearchthecurrentprojectdirectory,thenin
thefoldersidentifiedinReferencePaths,andtheninfoldersforthelistofassemblies
specifiedbytheAddReferenceswindow.
WithintheSolutionDemosolution,we’llcreateanewprojectforaclasslibrary.
Right-clickSolutionDemoandselectAdd|NewProject.Thistime,selectClassLibrary
insteadofConsoleApplicationandnameitClassLibraryDemo.ClickingOKwilladd
anewClassLibraryProjecttoyourSolutionDemoSolution.Youwillnowhavetwo
projectsinyoursolution.
TousethecodeintheClassLibraryproject,right-clicktheProjectDemoproject
andselectAddReference.Thistime,selecttheProjecttab,whichwillcontainallofthe
projectsthatbelongtothesamesolution.SelecttheClassLibraryDemoprojectandclick
OK.You’llseethereferencetoClassLibraryDemoappearintheReferencesfolderinthe
ProjectDemoproject.
TIP
Resetting References for Renamed Projects. You can rename any project by right-
clicking the project and selecting Rename. However, that doesn’t change the physical
folder name. If you want to change the physical folder name, close the solution (select
File | Close Solution) and then change the project folder name. When you re-open the
solution, Solution Explorer won’t be able to load the project. This is because the folder
name for the project in the solution file hasn’t changed. To fix this, select the project in
Solution Explorer and open the properties window. In the properties window, select the
file path property and either type the newly changed path or click the ellipses button to
navigate to the *.csproj file. Navigate back to Solution Explorer, right-click the project
that didn’t load, and select Reload Project.
Nowthatyouhaveareferencetoaclasslibrary,you’llwanttowritecodethatusesthe
objectsintheclasslibrary,whichyou’lllearnaboutnext.
Ifyou’reusingC#whenyoudothis,VSwillaskifyouwanttochangetheclassfilename
fromClass1toStudent.VBwillmaketheclassnamechangeautomatically,without
asking.Thisisaconvenientwaytokeepyourclassesandfilenamesinsync.Itiscommon
tocreateonlyoneclassperfile.Listing5-1showsthenewstudentfileafterrenamingand
addingcodetomakeitfunctional.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceClassLibraryDemo
{
publicclassStudent
{
publicList<int>GetStudentGrades(stringstudentName)
{
returnnewList<int>{80,100,95};
}
}
}
VB:
PublicClassStudent
PublicFunctionGetStudentGrades(ByValstudenNameAsString)As
List(OfInteger)
DimintListAsNewList(OfInteger)
intList.Add(80)
intList.Add(100)
intList.Add(95)
ReturnintList
EndFunction
EndClass
TheimportantpartsofListing5-1,forthecurrentdiscussion,isthatStudentisaclass
insideoftheClassLibraryDemonamespace.You’llneedtorememberthenamespaceso
thatyoucanobtainareferencetoaStudentinstancefromthecallingcode.Listing5-2
showshow.RememberthattheVBnamespaceisimplicitlysettowhateverisdefinedas
thenamespacesettingontheMyProjectpage,whichdefaultstotheprojectname.
128 MicrosoftVisualStudio2010:ABeginner’sGuide
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingClassLibraryDemo;
namespaceProjectDemo
{
classProgram
{
staticvoidMain(string[]args)
{
stringstudentName="Joe";
StudentmyStudent=newStudent();
List<int>grades=myStudent.GetStudentGrades(studentName);
Console.WriteLine("Gradesfor{0}:",studentName);
foreach(intgradeingrades)
{
Console.WriteLine("-"+grade);
}
Console.ReadKey();
}
}
}
VB:
ImportsClassLibraryDemoVB
ModuleModule1
SubMain()
DimgradesAsList(OfInteger)
DimstudentNameAsString="Joe"
DimmyStudentAsNewStudent
grades=myStudent.GetStudentGrades(studentName)
Console.WriteLine("Gradesfor{0}:",studentName)
Chapter5: CreatingandBuildingProjects 129
ForEachgradeIngrades
Console.WriteLine("-"&grade)
Next
Console.ReadKey()
EndSub
EndModule
OneitemtodrawyourattentiontoinListing5-2istheusingdirective(ImportsinVB),
specifyingthatyoucanusethetypesintheClassLibraryDemonamespacewithoutfully
qualifyingthem.Afterthat,youcanseehowListing5-2createsinstancesofStudentand
myStudentandcallsGetStudentGrades.
TIP
The call to Console.ReadKey in Listing 5-2 causes program execution to stop until the
user presses a key on their keyboard. If Console.ReadKey was not present, the program
would finish the Main method, which would close the application before you had the
chance to see the output.
Next,you’llwanttocompilethecodetoseeifthesyntaxisgoodandthenrunthe
programtoseeifitoperatesproperly.Thenextsectionexplainshowcompilingand
runningworkswithVS.
Compiling Applications
You’llfindseveralcompilationoptionsontheBuildmenu.Becausetherearesomany
options,itisn’talwaysintuitivewhichoptionyoushoulduse.Theoptionsarescopedto
eitherthecurrentprojectortheentiresolution.Thetopportionofthemenuappliesto
theentiresolution,andthesecondsectioniscontext-sensitive,applyingtothecurrently
selectedproject.Thefollowingsectionsdescribeeachsetofoptions,includingbuild,
rebuild,andcleanforbothprojectsandsolutions.
Building Solutions/Projects
Buildingtypicallymeansthatyourunthecompilertocompilesourcecodefiles.Sometimes
thebuildincludesmorethancompilation.Forexample,ifyouarewritingASP.NET
applications,VSwillgeneratecodebasedontheWebcontrolsonthepageandthenthat
generatedcodewillbecompiledwithnormalcode.Therefore,thetermbuildismore
accuratethancompile.
Duringanormalbuild,VSwillonlybuildtheitemsinaprojectorsolutionthatareout
ofdate.Morespecifically,onlyprojectsthathavechangesandeditswillberebuilt,
130 MicrosoftVisualStudio2010:ABeginner’sGuide
butprojectsthatareuntouchedwillbereusedasis.Abuildistypicallythefastestoption
duringnormaldevelopmentbecausebuildingonlyitemsthatareoutofdatemeansthat
therearelikelyitemsthatdon’tneedtobebuilt.Beaware,though,thatyou’lloccasionally
needtobuildeverythingtomakesureyouaren’taccidentallyworkingwitholdcode.
Rebuilding Solutions/Projects
Arebuildperformsthesameactionsasabuild,exceptthatitforcesthebuildofallitems
belongingtoaprojectorsolution.Reasonsforarebuildincludeensuringnewcodeyou’ve
writtenworkswithexistingcode,creatingafreshbuildfordeployment,andensuring
importantitemsarebuiltwhenanormalbuilddoesn’twork.
Manydevelopers,includingmyself,liketopullthelatestchangesfromsourcecontrol
intomysolutioneverymorningbeforestartingwork.Thisensuresthatthecurrentcodein
thesolutionwillbuildwithwhateverwasinsourcecontrol.Thiskeepsthecodeinyour
localsolutionfromdifferingtoomuchfromwhatisinsourcecontrol.
Beforeyoudeployanapplication,you’llwanttoperformarebuildtoensureallof
thecodebuilds.Dependingonyourprocess,youwillwanttotestthecodethatwasjust
rebuilt,priortodeployment.Therebuildensuresthattheapplicationyouarepreparingfor
deploymentisthemostcurrent.
Sometimesyournormalbuilddoesn’tworkcorrectlyoryou’reseeingbugsthat
seemtobeassociatedwithcodethatyou’vealreadywritten.WhileVSisagreattool
andmanagesdependenciesbetweenprojects,therearestillcomplexsituationswhere
everythingdoesn’tbuildcorrectly.Atthesetimes,youcantryarebuild,whichforcesthe
buildonallitemsofaprojectorsolution.
Arebuildtakesmoretimetoperformbecauseallitemsinaprojectmustberebuilt.
Ifyouhaveasmallproject,youmightnotnoticethedifferences.However,ifyouhave
afairlylargesolution,withdozensofprojects,asteadypatternofrebuildsthroughout
thedaycouldcutintoyourproductivity.Arebuildonaprojectisoftennotmuchmore
workthanabuildontheproject,butthereareprobablyedgecaseswherethedifference
intimewouldbenoticeable.Itistherebuildonthesolutionthatwillmostlikelygetyour
attention.Thatsaid,eachversionofVShasprogressivelyimprovedtheperformanceof
thebuildprocess,soyoushouldinterprettheperformanceasarelationbetweenbuildand
rebuild,ratherthanasastatementaboutVScomparedtoanyothertool.
Cleaning Solutions/Projects
Acleanoperationwilldeleteprojectoutputs,whichinclude*.dll,*.exe,orotheritems
producedbythebuildprocess.Youwouldoftenperformacleanoperationtoguarantee
thatalloutputsarefreshortoobtainasmallercopyoftheproject.
Chapter5: CreatingandBuildingProjects 131
Normally,afullrebuildensuresthatyouhavethemostup-to-dateoutputsavailable.You
couldalsoperformacleanoperationtoensurealloutputswereremovedandthenperforma
buildtoseewhichoutputswerecreated.Thismightgiveyouinsightintowhetherthebuildon
asolutionwasincludingalloftheprojects.Innormalcircumstances,VSmanagesallofyour
dependenciesforyou,asdescribedinthenextsection.However,inadvancedscenarios,some
developersmightoccasionallychangethesedependencies.Cleaningisatooltohelpyou
knowwhetheraprojectisreallybeingbuilt.Fromapracticalperspective,thisisrareandyou
couldinspectfiledatestotellthesamething,butcleaningisanotherpathyoucantake.
Amorecommonuseofcleanistoremoveoutputsfromtheprojecttomakeitsmaller.
Youmightwanttocompressaprojectorsolutionande-mailittoanotherperson,requiring
thatyouminimizethesizeoftheattachment.Whilecodefilesnormallycompressvery
well,*.dlland*.exefilescantakeupsomefilespace,evenwhenaddedtoacompressed
file.Ifyouperformacleanbeforecompressingthefiles,youwillusemuchlessfilespace.
CAUTION
Don’t alter project dependencies unless you really know what you are doing. The results
could be severe in that it can take a long time to fix dependencies in a large project.
The automatic dependency management provided by VS is very dependable, and you
should rely upon it whenever possible.
namespace.Youcanalsobuildcodethatdependsonyourowncustomconstantsby
addingyourownconstantstotheConditionalCompilationSymbolsboxasacomma-
separatedlistofstrings.
C#allowsyoutowritecodethatisclassifiedasunsafe,meaningthatyoucanuse
pointersandotherfeaturesinanunsafecontext.Unsafecodeisstillmanagedcode
(managedbytheCLR).However,theCLRcan’tverifythatthecodeissafebecause
unsafecodecancontainpointers.Thisisanadvancedfeatureandtheboxisunchecked,
ensuringthatyoumustcheckittooptintoenablethistypeofcoding.
Allwarningmessagesareassociatedwithalevel,andtheWarninglevelissetto4by
default,whichincludesallcompilerwarnings.Settingthistoalowerlevelwouldsuppress
thedisplayofallwarningsatthatlevelorhigher.Youcanalsosuppressspecificwarnings
byaddingthemtoacomma-separatedlistintheSuppressWarningsbox.Youreally
shouldn’tsuppresswarnings,asthissettingcouldcoverupanerrorthatwouldbehardto
detectotherwise.
Whenyoubuildanapplication,yourprogramwillrunevenifwarningsarepresentbut
willnotrunifthecompilerencounterserrors.Sometimeswarningsaresoimportantthat
youmightwanttotreatthemaserrors,andtheTreatWarningsAsErrorssectiongivesyou
flexibilityinhandlingwarning-as-errorscenarios.
Theoutputpathofanapplicationdefaultstobin\Debugundertheprojectfolderfor
Debugbuildsandbin\Releaseforreleasebuilds.Youcanchangethislocationifyoulike.
CheckingtheXMLDocumentationfilewillcauseXMLDocumentationcomments
tobeextractedfromyourcodeintoanXMLfilethatyouspecify.Checkingthisbox
increasesthetimeofthebuildprocess,soyouwon’tnecessarilywanttoleaveitonduring
Debugbuilds,whenyouaredoingmostofyourcoding.TheXMLdocumentationfilecan
beinputintothird-partytoolsthatautomaticallybuildtechnicaldocumentationforyou.
YouwouldonlychecktheRegisterForCOMInteropboxifyouwerebuildinga.NET
AssemblythatwasbeingcalledfromaCOMapplication.
Ifyou’redoingXMLserializationoftypesinanassembly,youcanturnontheGenerate
SerializationAssemblytospeedtheserializationprocess.
C#hasanothergroupofsettingsontheBuildEventstab.Youcanruncodebeforeor
afterthebuildforeachproject.Youcansettheconditionsuponwhenthebuildoccurs,
whichcouldbealways,onasuccessfulbuild,oronlywhenanupdateoccurs.Thebuild
eventshaveasetofmacrosyoucanaccessthatgiveyouinformationonthecurrentbuild
process.
VBhasoptionsthatarespecifictotheVBcompileronitsCompilepage,shownin
Figure5-11.
Chapter5: CreatingandBuildingProjects 135
MostoftheVBandC#compileroptionsaresimilar,exceptforOptionExplicit,
OptionStrict,OptionCompare,andOptionInfer.InVB,variabledeclarationbeforeuse
canbeturnedoff.WhenOptionExplicitison,youmustdeclareanyvariablesbeforeuse.
Youcanalsoassignanytypetoanotherbydefault,butOptionStrict,ifturnedon,will
forceyoutousecodethatperformsaconversionfromalargertypetoasmallertype,
oftenreferredtoasanarrowingconversion.
OptionComparecausescomparisonofstringstobedoneinabinaryfashion.However,
whenworkingwithdifferentlanguages,you’llwanttoconsiderchangingOptionCompareto
textsothatthecomparisonwillconsiderculture-specificissuesaffectingstringcomparisons.
OptionInferwillallowavariabletoassumeitstypebasedonwhatisbeingassignedtothe
variable,ratherthanexplicitlydeclaringthevariabletype.Here’sanexampleofinterredtype
onavariable:
DimstudentName="Joe"
Inthisexample,thetypeof"Joe"isclearlyaString.SinceOptionInferisturnedon,this
syntaxisvalidandstudentNamebecomesaStringbecausethatisthetypeofthevalue
beingassigned.
136 MicrosoftVisualStudio2010:ABeginner’sGuide
ClassDetailswindowprovidesadditionaldetailsonthemembersoftheProgram.csclass.
Figure5-13isaminimaldiagramofoneclasswithasinglemethod,Main,andyouwould
haveseenalloftheclassesinthecurrentprojectifthereweremore.Thiscouldbeagood
waytohelpyoulearnaboutanexistingbaseofcode.
Inadditiontocodevisualization,youhavetheabilitytoperformsomelightdesignwith
theClassDesigner,asdiscussedinthenextsection.
classnamedStaff,anormalclassnamedTeacher,aninheritancerelationshipwhereTeacher
derivesfromStaff,andanassociationfromProgramtoStaff.
Tocreateanewobject,drag-and-droptheobjectfromtheToolboxtotheClass
Designersurface;you’llseeaninputwindowsimilartoFigure5-15.
TheNewAbstractClasswindowinFigure5-15istypicalofmostoftheClassDesigner
objectsyoucanaddtoadiagramwhereyoufillintheinitialdatafornamingtheclassand
specifyingthefilethecodewillbeaddedto.NotallToolboxoptionsworkthisway,though;
associationsandinheritanceworkbyselectingtheitemintheToolbox,selectingtheobject
wherethelinebeginsintheClassDesigner,anddraggingthelinetotheobjectintheClass
Designerbeingreferenced.
TheothertwoplacesyoucanmodifydataareintheClassDetailsandProperties
windows.YoucanseehowIaddedtheGradePapersmethodinClassDetails.Youcanadd
memberstoanobjectyourselfbyclickingtheobjectinClassDesigner,andthenadding
thememberinClassDetails.TheGradePapersmethodalsohasaSummarycommentfor
documentationandaparameternamedpaperswithatypeofList<string>.
ThePropertieswindowiscontext-sensitive,showingyouwhatoptionsareavailable
forwhateveryouhaveselectedintheClassDesigner.InFigure5-14,theTeacherclassis
selectedinClassDesignerandtheSummarypropertyinthePropertieswindowwasfilled
inwithacomment.Listing5-3showsthecodefromtheTeacher.cs(Teacher.vbinVB)
filethatwasgeneratedafteralloftheseactionsinthegraphicaldesigner.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceProjectDemo
{
///<summary>
///TeachesClasses
///</summary>
publicclassTeacher:Staff
{
///<summary>
///Gradestudentpapers
///</summary>
///<paramname="papers">Paperstograde</param>
publicvoidGradePapers(List<string>papers)
{
thrownewSystem.NotImplementedException();
}
}
}
VB:
'''<summary>
'''TeachesClasses
'''</summary>
PublicClassTeacher
InheritsStaff
'''<summary>
'''Gradestudentpapers
'''</summary>
PublicSubGradePapers(ByValpapersAsList(OfString))
EndSub
EndClass
AsshowninListing5-3,codegeneratedfromtheClassDesignerincludesdefaultusing
directivesandthenamespaceasspecifiedinprojectproperties.Theclassname,Teacher,
Chapter5: CreatingandBuildingProjects 141
isthesameasthevisualobjectintheclassdiagram,andtheGradePapersmethodisthe
sameasspecifiedintheClassDetailswindow.YoucanalsoseethecommentonTeacher
asspecifiedinthePropertywindow.Allthat’sleftforyoutodoisreplacethecalltothrow
newSystem.NotImplementedExceptionwithyourowncodeinC#orjustaddyourcodeto
GradePapersinVB.
Summary
Youshouldnowknowhowtocreateasolutionandaproject.Youcansetproject
propertiesandaddnewmemberstoprojects.Additionally,youareabletoaddclass
librariestoaprojectandreferencethoseclasslibrariesfromotherprojectsthatusethose
libraries.Ifyoupreferamoreformaldesignprocess,VSofferstheClassDesigner,which
youlearnedtouseforbothvisualizationandcodegeneration.Thenextchapterbuilds
uponthecodingprocesswithVSbyshowingyouhowtodebugcode.
This page intentionally left blank
Chapter 6
Debugging with
Visual Studio
143
144 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● ExploringAvailableDebuggingTools
● SettingBreakpoints
● InspectingProgramState
● SolvingProblemswithVSDebuggingTools
M oreoftenthanwewouldlike,ourcodehasbugs.Fortunately,whenbugsdohappen,
youhavealotofhelpwithVS.ThischaptershowsyouhowtousetheVSdebugger
tofixproblemsbysettingbreakpoints,steppingthroughcode,andinspectingprogram
state.There’salsoasectionondevelopment-timetoolstoinspectthestructureofyour
code.Beyondsettingbreakpoints,you’lllearnhowtocustomizebreakpointsandhow
tomanagealistofbreakpoints.Thenyou’llseetheoptionsVShasforsteppingthrough
code.Thischapteralsoshowsyoumanywaystoseewhatthevaluesofvariablesarein
yourcodeandthevarioustoolsavailableforinspectingyourcode.First,we’llstartwith
someexamplecodeyoucanusetopracticetheconceptslearnedinthischapter.
C#:Program.cs
usingSystem;
namespaceDebugAndTestDemo
{
classProgram
{
staticvoidMain()
{
Customercust=newCustomer();
cust.Discount=.1m;
Orderord=newOrder();
ord.AddItem(5.00m);
ord.AddItem(2.50m);
cust.Order=ord;
decimaldiscount=cust.GetOrderDiscount();
Console.WriteLine("CustomerDiscount:{0}",discount);
Console.ReadKey();
}
}
}
C#:Customer.cs
namespaceDebugAndTestDemo
{
classCustomer
{
publicdecimalDiscount{get;set;}
publicOrderOrder{get;set;}
publicdecimalGetOrderDiscount()
{
returnOrder.Total*Discount;
}
}
}
C#:Order.cs
usingSystem.Collections.Generic;
146 MicrosoftVisualStudio2010:ABeginner’sGuide
namespaceDebugAndTestDemo
{
classOrder
{
privateList<decimal>orderItems=newList<decimal>();
publicdecimalTotal
{
get
{
decimalamount=0;
foreach(variteminorderItems)
{
amount=amount+item;
}
returnamount;
}
}
publicvoidAddItem(decimalamount)
{
orderItems.Add(amount);
}
}
}
VB:Module1.vb
ModuleModule1
SubMain()
DimcustAsCustomer=NewCustomer()
cust.Discount=0.1D
DimordAsOrder=NewOrder()
ord.AddItem(5D)
ord.AddItem(2.5D)
cust.Order=ord
DimdiscountAsDecimal=cust.GetOrderDiscount()
Console.WriteLine("CustomerDiscount:{0}",discount)
Console.ReadKey()
EndSub
EndModule
Chapter6: DebuggingwithVisualStudio 147
VB:Customer.vb
ClassCustomer
PropertyDiscountAsDecimal
PropertyOrderAsOrder
FunctionGetOrderDiscount()AsDecimal
ReturnOrder.Total*Discount
EndFunction
EndClass
VB:Order.vb
ClassOrder
PrivateorderItemsAsNewList(OfDecimal)
PublicReadOnlyPropertyTotal()AsDecimal
Get
DimamountAsDecimal=0
ForEachitemInorderItems
amount=amount+item
Next
Returnamount
EndGet
EndProperty
SubAddItem(ByValitemAsDecimal)
orderItems.Add(item)
EndSub
EndClass
AquicklookatthecodeinListing6-1tellsyouthatthisprogramismoresophisticated
thantheexamplesyou’veencounteredinpreviouschapters.Tounderstandwhatishappening,
startattheMainmethod,theentrypointoftheapplication.Therearetwoobjectsinstantiated
inMain,namelyCustomerandOrder.
AfterinstantiatingCustomer,youcanseethattheDiscountpropertyoncustisbeing
setto.1(10%).ThismeansthateachinstanceofCustomercanhaveauniquediscount
amount,whichcouldbeusefulifyouwantedtorewardgoodshoppinghabits.
Next,youcanseetheinstantiationofOrderandsubsequentcallstoAddItemonthe
objectreferenceord.Thiscodeonlyaddstheorderamount,butinarealscenarioit
wouldlikelybeaclasswithmorefieldstocarrythespecificdetailsoftheorderitem.The
CustomerclasshasanOrderproperty,whichthecodethenpassesourOrderinstance,
ord,to.Now,youhaveaCustomerwithadiscountamountandithasareferencetoour
specificOrder,whichinturnhasitems(representedherebytheitems’monetaryamount
onlyforbrevity).
148 MicrosoftVisualStudio2010:ABeginner’sGuide
Thisprogramcalculatesthetotalmonetarydiscountthatacustomerwouldreceiveforthat
orderbycallingtheGetOrderDiscountmethodontheCustomerinstance,whichthenreturns
thecalculateddiscountamounttobesubsequentlydisplayedontheconsole.Essentially,we
createdacoupleofobjectinstances,custandord,gavetheobjectinstancesthedatathey
needed,andtoldtheobjectinstancestodosomeworkforus.Theresultisaspecialdiscount
monetaryamountforagivencustomer,basedonthecustomer’sitemsordered.
AllofthecodeintheMainmethodisatthefirstlevelofthecallhierarchy.The
methodsandpropertiesinCustomerandOrderareatthesecondlevelofthehierarchy.
LookingatOrder,youcanseethatthereisaTotalpropertyandanAddItemmethod.
AddItemaddstheitemparametertoitsorderItemscollection.Totaliteratesthroughthe
orderItemscollection,firstcalculatingthenreturningthesumofallitems.Noticethatthe
CustomerclasshasaDiscountpropertythatholdsadecimalvaluethatwillbeusedasa
percentage.TheGetOrderDiscountmethodinCustomermultipliestheDiscountbythe
TotalinOrdertoreturnthediscountoftheorder.
It’simportantforyoutostudythisexampleandunderstandtherelationshipsand
communicationbetweenvariousobjects.Observethateachclasshasadistinctpurpose,
relatingtohowitisnamed.Thepurposeoftheclasshelpsdecidewhatdataandmethods
thatclasswillhave;OrderhasTotalandAddItem,andtheclassCustomerhasDiscount
andGetOrderDiscount.Eachobjectcommunicateswithotherobjects,cooperating
toperformatask.Forexample,itisCustomer’sresponsibilitytocalculateadiscount
becausetheCustomerclassknowswhatthediscountshouldbe(becausewetolditwhat
thediscountwasinMain).However,CustomermustcommunicatewithOrderbecause
Orderistheonlyobjectthatknowsabouttheorderitemsandhowtocalculatethetotal.
AlthoughI’veshownyouthecodeandexplainedhowitworks,it’softenusefultosee
theflowoflogicoftheactualrunningprogramyourself.VSincludesvariousvisualization
anddebuggingtoolsthathelpyouunderstandtheflowoflogic,whicharediscussednext.
Fromtheperspectiveofreuse,manycallsitestoamethodcouldindicatethatthe
methodisrelativelygenericandreusable.Whilealownumberofcallsitesmightnot
indicatethereusabilityofamethod,zerocallsitescertainlyindicatesthatthemethodis
notbeingusedandcanpotentiallybeeliminated.
Alotofcallsitescouldalsoindicatethatachangetoamethodcanhaveasignificant
impact.Lookingatthenumberofcallsitesthatamethodhascouldbeinformativefrom
theperspectiveofpassingdifferentvaluesorseeinghowmanychangeswillberequiredin
calledmethods.
Thepreviousdiscussionistohelpyouunderstandhowcallhierarchymightbe
useful.Now,let’slookathowcallhierarchyworks.First,rememberthatcallhierarchy
iscontext-sensitive,meaningthatwhatevercodeintheeditorhasfocusdefinesyour
pointofview.ThepointofviewforthisexamplewillbetheGetOrderDiscountmethod
intheCustomerclass,andwewanttoseethecallsitesofGetOrderDiscountandwhat
statementsinsideofGetOrderDiscountarecallsites.Tousecallhierarchy,eitherright-
clicktheGetOrderDiscountmethodintheeditorandselectViewCallHierarchy,orselect
GetOrderDiscountintheeditorandpressCTRL-K,T.VSshowstheCallHierarchywindow
inFigure6-1.
TheCallHierarchywindowinFigure6-1showsCallsToandCallsFromforthe
GetOrderDiscountmethod.CallsToisalistofcallsitestotheGetOrderDiscountmethod.
CallsFromisalistofstatementswithinGetOrderDiscountthatarecallsitesforother
classmembers.
Thedrop-downlistatthetopleftofFigure6-1,withMySolutionselected,identifies
howfarCallHierarchywilllooktofindCallsToandCallsFromcallsites.Theoptions
areMySolution,CurrentProject,andCurrentDocument,whichareself-explanatory.
150 MicrosoftVisualStudio2010:ABeginner’sGuide
Ifyou’vebeenworkingonyourcodeandwanttoupdatetheCallHierarchywindow,
clickRefresh.EverytimeyouviewCallHierarchy,theselecteditemisaddedtothelist.You
canusetheRemoveRootbuttontodeleteanitemfromthelist.TheToggleDetailsPane
buttonshowsandhidestheDetailspane,whichshowsthecodeandlocationofthecallsite.
InFigure6-1,theMainmethodisselected,whichshowsthecalltoGetOrderDiscountsoff
thecustinstanceofCustomerfromListing6-1.Theactualcodelineisshownalso.Youcan
double-clickthestatementtonavigatetheeditortothelocationofthatstatement.Infact,you
candouble-clickanycallsiteintheCallHierarchytonavigatetothelocationofthecallsite
intheeditor.
TheCallHierarchyshowsallofthepossiblepathsyoucantakethroughaspecific
pointincode.Whilequiteuseful,it’slimitedtoprovidingastaticviewofyourcode,and
itdoesnotprovidethedetailedinsightintoyourrunningprogramthatdebuggingmay
require.Whendebugging,youtypicallyneedtoviewtherunningstateofanapplicationat
aspecificpointintime.Thefollowingsectionsshowyouvariousfeaturesofthedebugger
thathelpyouinspecttheruntimebehaviorofcode.
Doabuildofyourapplication,whichwillproducevariousfilessuitablefordebugging.
Toviewthesefiles,right-clickthesolution,project,orfolderinSolutionExplorerand
selectOpenFolderinWindowsExplorer.Thennavigatetothebin\Debugfolder,which
shouldlooksimilartoFigure6-3.
TherearefourfilesinFigure6-3,twofortheapplicationandtwotosupportrunning
inthedebugger.DebugAndTestDemoCS.exeistheexecutableconsoleapplication,which
youmighthavealreadyexpected.A*.pdbfileisasymbolfilethathelpssynchronizethe
identifiersinyourcodewiththeexecutablefile,makingiteasiertostepthroughcodewith
theVSdebugger.
Therearetwofileswithvshostintheirname,whichareinstrumentaltothedebugging
process.A*.vshostfilemakesyourapplicationloadfasterduringdebugging,givesyou
theabilitytotestyourapplicationwithdifferentsecurityconfigurations,andallowsyouto
evaluateexpressionswhiledebugging.Thevshostfilesarefordebuggingonly,soyou
152 MicrosoftVisualStudio2010:ABeginner’sGuide
shouldnotdeploythemwithyourapplication;theywouldjusttakeupextraspaceandnot
serveapurpose.YounormallywantvshostfilesinplacewhendebugginginVS.There
arevariousdebuggersettingsyoucanconfigureinVSthataffectyoursessionandmodify
thevshostconfigurationfiles.OpenthepropertiespageandclicktheDebugtab,shownin
Figure6-4.
InFigure6-4,youcanseethattheConfigurationissettoDebugandthePlatformis
settox86.ThePlatformtargetcanbeAnyCPU,x86,x64,orItanium,dependingonthe
CPUyouarebuildingtheapplicationon.Thecompilerwillperformoptimizationsfor
theCPUtypeyouselect.Ifyou’rerunningVSona64-bitoperatingsystem,yourActive
solutionplatformmayshowasActive(AnyCPU).
TheStartActionsectionoftheDebugtabdetermineshowthedebuggingsessionbegins.
StartProjectisthedefault,StartExternalProgramallowsyoutoattachyourVSdebugging
sessiontoanalready-runningapplication,andStartBrowserWithURLletsyoudebuga
Chapter6: DebuggingwithVisualStudio 153
Webapplication.Generally,you’llonlyuseStartProjectforadesktopapplication.The
propertypageschangeforWebapplications,whichautomaticallyruninabrowser.
Youcanaddaspace-separatedlistofvaluesforcommand-linearguments.Ifyou’re
buildinganapplicationthatneedstoberunfromacommandwindoworfromacommand
script,thismethodisveryusefultotestanddebugaspecificcommand-lineconfiguration.
Youcanthenreadthevaluesyou’veenteredintotheCommandLineArgumentstextbox
byreadingthemfromtheargsarraypassedtotheMainmethod.
Aworkingdirectoryistherootlocationofwhereyourprogramreadsandwritesfiles.
Bydefault,thislocationisbin\DebugforDebugconfigurationsandbin\ReleaseforRelease
configurations.Youcanchangetheworkingdirectorylocationbyputtingafilepathinthe
WorkingDirectorypropertybox.
UseRemoteMachineisanadvancedscenariowhereyoucandebuganapplication
runningonaremotemachine.Todothis,youwouldneedtoinstallremotedebugging
softwareontheremotemachine,ensuretheOutputpathoftheBuildtaboftheProperties
154 MicrosoftVisualStudio2010:ABeginner’sGuide
windowspecifiesthelocationoftheexecutablefileoftheprogramtobedebugged,that
theoutputfolderisshared,andthatyourapplicationhaspermissionsonthesharedfolder.
Thefocusofthisbookisonmanagedcode,whichrunsonthe.NETCLR.VShasthe
abilitytodebugunmanagedcode,suchasthatwritteninC++thatcommunicatesdirectly
withtheoperatingsystem.Generally,youwanttoleavetheEnableManagedCode
Debuggingboxuncheckedunlessyouarewritingmanagedcodethatinteroperateswith
unmanagedcode,suchasaCOMDLLlibrary,andneedtheabilitytodebugboth.VSwill
allowyoutoopenSQLServerstoredprocedures,setabreakpoint,andstepthroughthe
storedproccodefordebugging.Ifyouneedtodebugstoredprocedures,makesureyou
checkthisbox.
NOTE
Managed code refers to code that runs on the .NET Common Language Runtime
(CLR). The CLR is a virtual machine that provides several services such as memory
management, code execution, garbage collection, security, and more. In contrast to
managed code, there is also code that is called unmanaged code. Unmanaged code
does not use the .NET CLR; instead it runs directly on the computer and communicates
with the operating system. With unmanaged code, you must manage your own memory
and write low-level code to accommodate all of the services that the CLR would normally
give you. You can use VS to write unmanaged code in C++, but this book focuses on
C# and VB, which produce executable files that run managed code on the CLR.
TheEnableTheVisualStudioHostingProcesssettingiswhatcausedthevshostfiles
tobegeneratedintheoutputfolder.Normally,youwanttoleavethisboxcheckedbecause
ofthebenefitsofvshosts,describedpreviously.Theonlyexceptionmightbeifyouhad
auniquesituationwheretheservicesprovidedbythevshostsprocessconflictedwiththe
codeyouwererunning,whichwouldbeanadvancedandrarescenario.
TIP
In earlier versions of VS, you would occasionally get a file permission error on the
vshosts file, which was caused by the fact that there were file locks on the file. This
can occur if you have attached to the running process from another instance of VS
or the process shut down improperly in a sequence that didn’t release the file lock on
vshosts. One of the work-arounds is to uncheck the Enable The Visual Studio Hosting
Process box, rebuild, recheck the Enable The Visual Studio Hosting Process box, and
build again. You also have the choice of restarting your OS, whichever you find easier.
This scenario doesn’t point to a deficiency in VS or the operating system, because
the file locks are necessary when an application is running. Rather, the scenario is a
consequence of having a bug in your code or improperly shutting down an application.
Inadditiontopropertysettings,youhaveaplethoraofoptionsavailableviatheOptions
window,whichyoucanopenbyselectingTools|Options,asshowninFigure6-5.
Chapter6: DebuggingwithVisualStudio 155
AsyoucanseeinFigure6-5,thereareavarietyofoptionsthatallowyoutoconfigure
debugging.TheprimarydifferencebetweenprojectsettingsandOptionssettingsisthat
projectsettingsareforthatoneproject,butOptionssettingsletyouchangethesettingsfor
allprojectsandhavethosesettings,whenapplicable,applytoanynewprojectsyoucreate.
Therefore,iftherearedefaultsettingsyouwantonallprojects,visittheOptionssettings
tosetthemfirst.Theoptionsaremuchtoonumeroustolisthere,andmanyofthemdeal
withadvancedscenariosthatareoutofscopeofthisbook.Ifyoueverhaveaquestion
aboutwhetheracapabilityisavailableorifyouneedtosavesettings,youshouldvisitthe
Optionswindowtoseeifthatcapabilityisavailable.Nowthatyoursystemisconfigured
fordebugging,youcansetbreakpointsandstartthedebuggingprocess.
Setting Breakpoints
Breakpointsareplacesinyourcodewhereyouwanttheprogramtoautomaticallypause
fromrunning,similartowhenyoupushthepausebuttonwhilewatchingamoviewith
yourhomeDVDorBlu-rayplayer.Onceyourprogramhits(stopson)yourbreakpoint,
youwillbeabletoperformdebuggingtasks,whichcouldbeviewingthevaluesof
variablesatthisfrozenpointintime(programstate),evaluatingexpressions,orediting
codeandcontinuingexecution.Thefollowingdiscussionshowsyouhowtocreateand
managebreakpointsinyourapplication.
156 MicrosoftVisualStudio2010:ABeginner’sGuide
Creating a Breakpoint
Tocreateabreakpoint,youneedtoopenaprojectandhaveacodefileopenintheeditor.A
goodprojectchoicewouldbetheexampleapplicationwithcodefromListing6-1.IntheVS
editor,thereisamarginontheleftside.Ifyouclickinthismargin,VSwillsetabreakpoint
onthematchingcodestatement.Clickingastatementincodetogiveitthefocusandpressing
F9setsabreakpointtoo.You’llseeareddotinthemarginandthematchingstatement
highlightedinred,asshowninFigure6-6.Notethatyoumayonlysetabreakpointoncode
thatactuallygetsexecutedatruntime.Ifyoutrytoselectalineofcodethatdoesnot,such
asanamespacenamedefinition,thereddotwillnotappearandyou’llseeamessageatthe
bottomofVSsaying,“Abreakpointcouldnotbeinsertedatthislocation.”
ToensureVSstopsonabreakpoint,theapplicationmustberunningindebugmode.
YoucanstarttheprogramrunningindebugmodebyselectingDebug|StartDebugging,
pressingF5,orclickingtheStartWithDebuggingtoolbarbutton(theonewiththegreen
arrow).ThebreakpointinFigure6-6isonthecalltoGetOrderDiscountintheMain
method.Whentheprogramhitsthebreakpoint,thebreakpointlinewillturnyellowand
therewillbeayellowarrowonthereddotinthemargin.ClickingtheContinuebutton
(whichisthesamegreenarrowbuttonusedtostartdebugging)orpressingF5willcause
VStoresumeexecution.Anytimeyouwanttostopdebugging,selectDebug|Stop
Debugging,pressF5,orclicktheStopDebuggingtoolbarbutton(smallbluesquare).
Figure6-6 A breakpoint
Chapter6: DebuggingwithVisualStudio 157
TIP
If you write a program that is doing a lot of work, or very little work but is stuck in
an endless loop that you inadvertently created, you can pause execution by selecting
the blue pair of vertical bars button found to the left of the square blue stop button.
When you do this, your program stops at whatever line of code it was executing at the
moment you selected the pause button. You can then resume from that point. This button
works much like the pause button on a remote control or a personal media player.
Customizing a Breakpoint
Theprecedingexplanationdescribedhowtosetalocationbreakpoint,whereexecution
stopsonadesignatedlineincode.However,youcanmakeaprogramstopexecuting
basedonvariouscriteria,suchashitcount,conditions,andmore.Toseewhatelseis
available,setalocationbreakpointandthenright-clickthedotinthemargintoview
thecontextmenu.Table6-1describeseachofthebreakpointoptionsavailablefromthe
breakpointcontextmenu.
Youcanalsosetafunctionbreakpointbyclickingonthemethodtobreakonand
selectingDebug|NewBreakpoint|BreakAtFunctionorpressingCTRL-D,N.
Option Meaning
Delete Breakpoint Removes the breakpoint.
Disable/Enable If you don’t want to delete the breakpoint because you’ll use it again, you can
Breakpoint disable the breakpoint and then enable it later when you want to use it again.
Location This is set when you click in the margin. You can change features of the location
through a dialog window.
Condition Allows you to enter an expression that can cause the program to stop if either the
expression evaluates to true or the value of a variable has changed. The expression
is based on variables in your code.
Hit Count Makes the program break on that line every time, after a number of times the line
has executed, when the count is a multiple of a number (i.e., every nth time), or
when the number of hits is greater than or equal to a number.
Filter The breakpoint will only be hit (causing execution to pause) for any combination of
machine, process, or thread choice that you set.
When Hit Sets a tracepoint that prints a message to the output window. The message is
configurable to include output of various system values like function, thread, and
more. You can view the message in the Output window by selecting View | Output
Window or pressing CTRL-ALT-O. You also have the option of running a macro when
the breakpoint is hit.
Edit Labels You can associate breakpoints with labels to help organize breakpoints into groups.
Export Lets you export breakpoints into an external XML file.
Managing Breakpoints
Overtime,breakpointscanbesetacrossmanylocationsinyourproject.Youcanmanage
allofthesebreakpointsinacentrallocationbyselectingDebug|Windows|Breakpoints,
whichwillshowthewindowinFigure6-7.
MuchofthefunctionalityoftheBreakpointswindowhasbeenexplainedalready,
exceptthatthetoolbaroptionsapplytoallofthebreakpointsthatarecurrentlychecked.
Clickingacolumnsortsthecontents.TheSearchboxhelpsyoufilterbreakpoints,andthe
InColumnsboxhelpsfocusonwhatthesearchappliesto.Thereareexportandimport
buttonsonthetoolbarthatallowyoutorespectivelysaveandretrievebreakpointsto
andfromanXMLfile.Double-clickinganybreakpointtakesyoutothelocationinthe
editorwherethebreakpointisset.Right-clickingabreakpointshowsacontextmenuwith
optionsthathavealreadybeendiscussedinthissection.
Onceyousetabreakpoint,youcanstepthroughcodetoseewhattheexecutionflow
oftheprogramis,asisdiscussedinthenextsection.
Operation Explanation
Step Over Executes the code in the current line and moves to the next line of code where
it again pauses, waiting for your instruction. Perform a Step Over by selecting
Debug | Step Over, pressing F10, or clicking the Step Over button in the toolbar.
You can also right- click and select this option. Most Visual Studio developers will
have the F10 shortcut memorized in short order.
Step Into Specific When the current line is on a method call, a Step Into will move control to the first
line of the method being called and execution will pause there. Perform the Step
Into by selecting Debug | Step Into, pressing F11, or clicking the Step Into button in
the toolbar. F11 is the fastest way for you to do this operation.
Step Out If you’re in a method, you can move back to the caller by performing a Step Out
operation. Perform a Step Out by selecting Debug | Step Out, pressing SHIFT-F11, or
clicking the Step Out button on the toolbar. Note that no lines of code are skipped
inside the function; they still run following your program’s logic. Your program will
automatically pause at the line of code following this function’s return.
Run to Cursor Sometimes you want to execute a block of code and stop at a certain line. You
could set another breakpoint and run until you hit the breakpoint. However, a
quicker way when you don’t want to keep a new breakpoint around is to right-click
the line you want to stop at and select Run To Cursor. Again, no lines of code are
skipped; the program will merely pause when it gets to the line you placed your
cursor on. Optionally, you can click the line to run to and press CTRL-F10. This is
particularly useful if you don’t feel like stepping through every iteration of a loop.
Set Next Statement You can skip forward and backward over multiple lines of code without executing
the skipped code. For example, it’s easy to step over a method, only to realize
that you really wanted to step into that method. You don’t want to restart the
application unless you need to. To get back to that line of code so that you can
step into the method call, select the yellow arrow in the margin and drag it back
up to the method call. Then you can do a Step Into. Alternatively, if you have one
or more statements that you don’t want to execute, drag the yellow arrow in the
margin to the statement following the code you don’t want to run and then use
stepping operations to resume your debugging session. This technique is also
quite handy when you are using the Edit and Continue feature, where you can
change your program on the fly, experiment with different coding ideas you may
have, and rerun those lines of code instantly. Note that VS does not reset variables
back to initial states, so you may have to manually reset values in order to get the
results you expect.
AStepOveroperationexecutesthecodeinthecurrentlineandmovestothenext.You
canperformaStepOverbyselectingDebug|StepOver,pressingF10,orclickingtheStep
Overbuttoninthetoolbar.
Younowknowhowtostepthroughcode,whichisuseful.However,theabilitytosee
thevaluesofvariablesandwatchthemchangeisanimportantskill,whichyoulearnabout
inthenextsection.
160 MicrosoftVisualStudio2010:ABeginner’sGuide
NOTE
When inspecting the state of your application, you’ll need to keep the concept of scope
in mind. When a variable is in scope, you will be able to see the variable’s value. Scope
is defined within a block. In C#, the block is defined with curly braces, and VB defines
a block with begin and end statements. A couple examples of scope involve class fields
and local variables. A private class field would be in scope for all the methods of that
class but not in another class. A local variable would be in scope for all statements
of the method it is defined in, but would be out of scope for other methods. Another
scenario is a for loop that defined a variable in its body—the variable would be in
scope for the body of the loop but out of scope outside of the loop body.
listcanbequitelong,dependingonhowmanyvariablesareinscope.Youwouldwantto
usetheLocalswindowtofindanyvariablesbeingaffectedbythecurrentalgorithm.In
comparison,Figure6-9showstheAutoswindow.
NoticethattheAutoswindowprovidesamorefine-grainedviewofbothvariablesand
thepropertiesofobjectsfromthecurrentandpreviouslines.YouwouldwanttouseAutos
foramoretargetedviewofwhatiscurrentlyhappeninginthecode.
Watch Windows
AWatchwindowallowsyoutocreateacustomlistofvariablestowatch.Youcandrag
anddropvariablesfromtheeditorortypeavariablenameintheWatchwindow.Selecting
Debug|Windows|WatchwilldisplayalistoffourWatchwindows,whereyoucanhave
fourdifferentsetsofdatatoinspectatonetime.Figure6-10showsaWatchwindowwith
avariable.
TheLocalsandAutoswindowscansometimesbecomecrowdedwithtoomany
variablesandslowyoudownasyourcodegetsmorecomplex,especiallywhenthe
variablesyou’reinterestedinareatthebottomofthelistorsofarapartthatyoumust
scrollbetweenthem.AnotherbenefitoftheWatchwindowisthatyoucandrilldown
intoanobjecttoshowavaluewithoutcontinuouslyexpandingthetreeview.An
exampleofthisistotypecust.Order.TotalasshowninFigure6-10,toseetheresults
oftheTotalspropertyoftheOrderpropertyofthecustinstance.Inaddition,you
caneditthevaluesofyourvariablesandpropertiesinthiswindowbyeitherdouble-
clickingthecurrentvalueshownintheValuecolumnorright-clickingthevariable
nameandchoosingEdit.Whenthevaluechanges,itchangescolorfromblacktoredto
letyouknowithaschanged.Thistechniqueofeditingyourvaluesontheflycomesin
quitehandy,especiallywhenyoufindyourselfslidingtheyellowarrowuptoprevious
linesofcodeinordertore-runthemwithoutrestartingyourprogram.Thesetechniques
shouldprovetobeahugetimesaver.
theQuickWatchwindowwillshowthatexpression.Figure6-13showstheQuickWatch
windowinuse.
ClickingtheReevaluatebutton,showninFigure6-13,willshowtheresultsof
evaluationintheValuearea.TheValueareawillonlyholdthecurrentexpression.Ifyou
wanttosaveanexpression,clickAddWatch,whichwillloadtheexpressionintoaWatch
window.BeawarethatclosingtheWatchwindowwillremoveyourexpression,butthe
expressionwillbepartofahistorylistthatyoucanselectfrom.
VSwilllocatethepinnedvalueaftertheline,andyoumightnotseethevalueifit
occursonalonglinethatexceedsthewidthofyourscreen.Fortunately,youcanclickthe
pinnedvalueanddragittowhereyouwantonthescreen.Toavoidconfusion,remember
tokeepthepinnedvaluelocatedclosetothevariablewhosevalueisdisplayed.
Right-clickthepinnedvaluetodisplayacontext-sensitivemenuwithoptionsforEdit
Value|HexadecimalDisplay|Add/RemoveExpression.Figure6-14showshowIadded
theexpression(discount*100).ToString("p")toshowthevalueasapercentage.Adding
expressionscanmakethevaluemorereadableorallowyoutoaddrelatedexpressionsto
seehowthevalueproducesothercomputedresultsonthefly.
YoucanclosethepinnedvaluebyhoveringoverthepinnedvalueandclickingtheX
(closeicon).
IntelliTracecouldbeusefulifyousteppedoverastatementthatchangedthevalueof
avariableandneededtogobacktoseewhatthevariablevaluewasbeforeyoustepped.
Figure6-15showsthisscenario,wherethehighlightedevent,Breakpointhit:Main,
allowsyoutoviewLocalsorCallStack.Theimportantdistinctionisthatthevalues
shownareforthepointintimewhenthateventoccurred,notthecurrenttime,whichcan
beveryvaluableinformation.AnotherimportantapplicationofIntelliTraceistoinspect
IntelliTracelogfilesthatwereproducedbyanotherdeveloperorthenewMicrosoftTest
andLabtoolthatrecordsatester’stestingsession.
YoucanconfigureIntelliTraceoptionsbyselectingTools|Options|IntelliTrace.
IntelliTracewillcreatealogfilethatexistsaslongasVSisrunning.WhenVSstops,the
logfileisdeleted,soit’simportantthatyoucopythisfilebeforeshuttingdownVS.The
locationofthelogfileisontheAdvancedbranchofIntelliTraceinTools|Options.
Ifyoureceivealogfilefromanotherdeveloper,youcanloaditbyselectingFile|
Open|OpenNew.Thenyoucanviewdebugginghistorytoviewthestateofthe
applicationduringeacheventofthesession.
handlingbaddataandfixingnullreferences.Theprogramitselfisnotparticularly
sophisticated,butitcontainsjustenoughlogictoleadyoudownaratholeandshowyou
howtoworkyourwayout.First,we’lllookattheprogram,andthenwe’llfollowupwith
twobug-fixingexercises.
VB:
PublicClassCustomer
PropertyFirstNameAsString
PropertyLastNameAsString
EndClass
Thisistheminimalinformationrequiredforthisdemo,andanyclassthatyoubuild
willhavemoreproperties.Noticethatbothpropertiesaretypestring.
168 MicrosoftVisualStudio2010:ABeginner’sGuide
VB:
PublicClassCustomerRepository
PublicFunctionGetCustomers()AsList(OfCustomer)
DimcustomersAsNewList(OfCustomer)From
{
NewCustomerWith
{
.FirstName="Franz",
.LastName="Smith"
},
NewCustomerWith
Chapter6: DebuggingwithVisualStudio 169
{
.FirstName="Jean"
},
NewCustomerWith
{
.FirstName="Wim",
.LastName="Meister"
}
}
Returncustomers
EndFunction
EndClass
TheGetCustomersmethodreturnsaList<Customer>(List(OfCustomer)inVB).For
thepurposesofthisdiscussion,howtheGetCustomersmethodworkswon’tmatter.Such
amethodcouldeasilygetcustomersfromadatabase,Webservice,orotherobject.For
simplicity,GetCustomersinitializesaListwithCustomerobjects.Thepartofthismethod
thatisparticularlyimportantisthecustomerwhoseFirstNamepropertyissetto“Jean”.
Noticetheblankspaceappendedtothename,whichisrequiredtomakethisscenario
behaveasdesigned(i.e.,tointentionallycreateabug).It’salsoconspicuousthatthe
CustomerobjectwithaFirstNamepropertysetto“Jean”alsodoesnothaveaLastName.
foreach(varcustincustomers)
{
//1.FirstBug
if(searchName==cust.FirstName)
{
Console.WriteLine(
"Found:{0}{1}",
cust.FirstName,
cust.LastName);
customerFound=true;
}
}
if(!customerFound)
{
Console.WriteLine("Didn'tfindcustomer.");
}
Console.ReadKey();
}
}
VB:
ModuleModule1
SubMain()
DimcustRepAsNewCustomerRepository
DimcustomersAsList(OfCustomer)
customers=custRep.GetCustomers()
DimsearchNameAsString="Jean"
DimcustomerFoundAsBoolean=False
ForEachcustAsCustomerIncustomers
'1.FirstBug
If(searchName=cust.FirstName)Then
Console.WriteLine(
"Found:{0}{1}",
cust.FirstName,
cust.LastName)
customerFound=True
EndIf
Next
Chapter6: DebuggingwithVisualStudio 171
If(customerFound=False)Then
Console.WriteLine("Didn'tfindcustomer.")
EndIf
Console.ReadKey()
EndSub
EndModule
NoticethatthesearchNamevariableissetto“Jean”.Withintheloop,thesearchName
iscomparedwiththeFirstNamepropertyofeachCustomerinstanceforequality.Here’s
theoutputfromwhentheprogramruns:
Didn'tfindcustomer.
Whatissupposedtohappenisthattheprogramshouldfindthematchingrecordand
printitout,butthat’snotwhathappens.Hereisthefirstbug,andthefollowingdiscussion
describeshowtofindthecauseofthebugusingtheVSdebugger.
1.StartbysettingabreakpointontheforeachloopintheMainmethod.Thiswasn’tan
arbitrarydecision.Instead,consideringthenatureoftheproblem,Iselectedapartof
theprogramthatislikelytobeginprovidingacuetowhattheproblemis.Lookingat
theprogram,oneofthereasonsthattheprogrammightnotfindthesearchNameisthat
wearen’tgettingdata,causingtheprogramtonotexecutethebodyoftheforeachloop.
2.PressF5toruntheprogramindebugmode.Thiswillexecutetheprogramandmakeit
stopontheforeachloop,makingitpossibletolookatprogramstate.
3.AfterVShitsthebreakpoint,hoverovercustomerstoseeifthereareanyvalues.
You’llobservethatcustomersdoeshavethreevalues.Thefactthattherearecustomers
indicatesthattheforeachloopisexecutingandwe’veeliminatedthatasapossibility.
172 MicrosoftVisualStudio2010:ABeginner’sGuide
4.Next,setabreakpointontheifstatement,right-clickthebreakpoint,andsetthe
conditionasfollows:
C#:
cust.FirstName=="Jean"
VB:
cust.FirstName="Jean"
Thegoalhereistoseewhathappenswhentheifstatementfindstherecordmatching
thesearchName.Atthispoint,we’reassumingthatJeandoesexistinthedata.Working
withasmallprogram,youcanusewindowssuchasAutos,Locals,orWatchtofind
thisrecord.However,manyreal-worldscenarioswillgiveyoualistwithmanymore
records.Therefore,ratherthanwastetimedrillingdownthroughdozensofrecords,use
theVSdebuggertohelpfindtherecordquickly.Keepinmindthatallthebestplans
don’talwaysworkout,asyou’llsoonsee,buttheprimarypointistakingthemost
productivestepfirst.Settingaconditionalbreakpointdemonstrateshowyoucanset
conditionsthatcanavoideatinguptimecausedbysteppingthroughloops.
5.PressF5toruntheprogram.Youexpecttohitthebreakpoint,butthatwon’thappen.
Confusing?Weknowthatthereisn’tanythingwrongwiththelogic,becausetheif
statementconditionisasimpleequalityoperator.Perhapswe’velookedinthedatabase
orwhateversourcethedatacamefrom,butit’sgiveninthisscenariothatJeanis
definitelyinthedata.However,thisillustratesacommonproblemwherethequalityof
datayouworkwithislessthandesired.
6.Thistime,changethebreakpointconditionontheifstatementasfollowsandre-runthe
program:
C#:
cust.FirstName.Contains("Jean")
VB:
cust.FirstName.Contains("Jean")
Remember,wesuspectbaddata,sothecalltoContainsonthestringassumesthatthere
mightbesomeextraneouswhitespaceorothercharactersaroundthenameinthedata.
Hoverovercust.FirstNameorlookatcustinoneofthedebugwindowstoverifyitis
therecordyouarelookingfor.Thisbreakpointwillpauseonanyrecordsthatcontain
thesequenceofcharacters“Jean”,suchasJean-Claude.So,youmighthavemultiple
matchesthataren’twhatyouwant.Thebenefitisthatthenumberofrecordsyoumust
Chapter6: DebuggingwithVisualStudio 173
lookatismuchfewerandyoucansavetime.Ifyouhavemultiplerecords,youcan
pressF5andthebreakpointwillpauseoneachrecord,allowingyoutoinspectthe
value.Inthiscase,therecordsetissosmallthatwehittherightrecordimmediately.
7.PressF10tostepovertheifcondition.Thiswilltelluswhethertheconditionisbeing
evaluatedproperly.Inthiscase,VSdoesnotstepintotheifstatementbutinstead
movestotheendoftheifstatement,meaningthatsearchNameandcust.FirstNameare
notequal.Thismeansyouneedtotakeacloserlookatcust.FirstNametoseewhatthe
problemiswiththedata.
8.Next,we’lluseacoupleoftheVSdebuggertoolstoinspectcust.FirstNameandfind
outwhytheequalitycheckisnotworking.OpentheImmediatewindow(CTRL-D,I)and
executethefollowingexpression:
cust.FirstName
whichwillreturnthis:
"Jean"
Here,youcanseethattheresulthasatrailingspace—dirtydata.Clearly,“Jean”does
notequal“Jean”becauseoftheextracharacterinthedata.Therearevariousnon-
printablecharactersthatcouldshowup,andVScanhelpheretoo.
9.OpenaMemorywindow(CTRL-D,Y),typecust.FirstNameintotheAddressbox,and
pressENTER.Thiswillshowthehexadecimalrepresentationofthedataatthememory
locationofthevariable,showninFigure6-16.
ThelayoutoftheMemorywindowstartswithanaddressontheleft,whichis
scrolleddowntothelinewherethedataincust.FirstNamevariablefirstappears.
Inthemiddleisthehexrepresentationofthedata.Thefinalcolumnhasareadable
representationofthedatawhereanycharactersthatdon’thaveareadablerepresentation
appearasdots.Youcansee“.J.e.a.n.”onthefirstlineofthethirdcolumn..NET
charactersare16-bitUnicode,andthedataforthecharacteronlyfillsthefirstbyte,
resultinginthesecondbytebeingsetto00,causingthedotsbetweencharactersyou
seeinthefirstcolumn.Ifthedatausedanothercharacterset,suchasJapaneseKanji,
youwouldseedatainbothbytesofthecharacter.Thehexrepresentationofthisdata
inthesecondcolumnis“004a00650061006e0020”.LookingattheUnicode
representation,whichyoucanfindathttp://unicode.org/,you’llseethatthehexand
visualrepresentationofthecharactersmatch.
YoucanseethatI’vehighlightedthe0020attheendofthefirstlineofthesecond
columninFigure6-16,whichprovesthatJeanisfollowedbyaUnicodespacecharacter.
Knowingthisinformationmighthelpyoushareinformationwithsomeonewhois
responsibleforthedata,lettingthemknowthatthereareextraneousspacesinthedata.
Somecomputerorsoftwaresystemsmightevenuseothertypesofcharacters,perhaps
aproprietarydelimiterforseparatingdata,andaccidentallysavethedatawiththe
delimiter.
1.PressSHIFT-F5tostopthepreviousdebuggingsession.
2.Implementafixbycommentingoutthecontentsoftheforeachloopandreplacingwith
codethatprotectsagainstextraneousspacesinthedata,asfollows:
C#:
varfirstName=cust.FirstName.Trim();
varlastName=cust.LastName.Trim();
if(searchName==cust.FirstName)
Chapter6: DebuggingwithVisualStudio 175
{
Console.WriteLine(
"Found:{0}{1}",
firstName,
lastName);
customerFound=true;
}
VB:
DimfirstNameAsString=cust.FirstName.Trim()
DimlastNameAsString=cust.LastName.Trim()
If(searchName=cust.FirstName)Then
Console.WriteLine(
"Found:{0}{1}",
cust.FirstName,
cust.LastName)
customerFound=True
EndIf
Next
Noticethatthefixwastousethestring.Trimmethodtoremovetheextraneousspace
fromthedata,assigningthecleanresultstolocalvariables.Trimdefaultstousingthe
spacecharacterbuthasoverloadsthatallowyoutospecifyadifferentcharacter,justin
casetheactualcharacteryousawinFigure6-16wassomethingotherthanaspace.The
restofthelogicusesvariableswiththecleandata.
3.PressF5toruntheprogramandseeifthefixworks.Unfortunately,you’restoppedin
yourtracksbythefactthatanewerroroccurs:aNullReferenceException.Unlikeruntime
errorsthatgiveyouwrongdata,VShelpsgreatlybybreakingonexceptionswhenthey
occurinthecode.Thenextsectiondescribesthiserror,theNullReferenceException,in
greaterdetailandprovidesinformationtohelpyoudealwiththeproblemwhenitoccurs
inyourprograms.
theprogram.Inthisparticularexample,VSpausesonthelinethatcleansLastName
properties,repeatedhereforyourconvenience:
C#:
varfirstName=cust.FirstName.Trim();
varlastName=cust.LastName.Trim();
VB:
DimfirstNameAsString=cust.FirstName.Trim()
DimlastNameAsString=cust.LastName.Trim()
Ifyourecall,thereasonforcallingTrimontheFirstNameandLastNameproperties
wastocleanthedatapriortoperformingfurtheroperationsonthatdata.Whilewewere
concernedaboutFirstName,wealsocalledTrimonLastNameaswelltohelpprotect
againstinvaliddatatheretoo,justtobesafe.ThefollowingstepsshowyouhowtouseVS
toanalyzethecurrentsituationandmakeaneffectivedecisiononanappropriatefix.
1.IfVSisn’trunning,restarttheprogramandletitrununtilVSpauseswitha
NullReferenceException.
2.Hoverthecursorovercust.LastNametoviewthevalue.Alternatively,youcanlookin
oneofthedebuggingwindowstoseethevalue.ObservethatLastNameisnull.
Thisisthecriticalpointintheanalysis,findingthevaluethatisnull.Itwasclearthat
custisnotnullbecausethepreviousstatement,cleaningFirstName,executedwithout
errorasverifiedbyinspectingthefirstNamevariable.Thisexamplemakesitvery
easytofindthenullvaluebecauseitoccurredonthelinewhereVSpaused.Inmore
challengingsituations,youcouldbepassinganobjecttoamethodinathird-party
librarywhereyoudon’thavethecodeandVSwillpauseonthelinewiththemethod
call.Inthatcase,youhavetoinspectthevaluesbeingpassedtothemethodtoseeif
anyarenull.
Onceyou’vefoundthenullvalue,youmustunderstandwhythecoderaisedthe
NullReferenceExceptionerror.Anullvalueistheabsenceofavalue;nothingis
assignedtothevariable.Ifyoutrytoreferenceavariablewithnullassignedtoit,you
willreceiveaNullReferenceException.Thismakessensebecauseyouaretryingto
performanoperationonavariablethathasnodefinition.Inthisparticularexample,
LastNameisnull,butwe’restillreferencingLastNamebycallingtheTrimmethod.
Thisisillogicalbecausethereisnotastringtotrim;thestringvariableissettonull.
Chapter6: DebuggingwithVisualStudio 177
YouwanttheNullReferenceExceptiontoberaisedbecauseitprotectsyoufrom
performinganinvalidoperationinyourcode.Afteryou’vefoundthenullvalueand
ascertainedthereason,it’stimetofindoutwhythevalueisnullinordertomakean
informeddecisiononafix.
3.IntheImmediatewindow,typethefollowingcommand:
C#:
customers.IndexOf(cust)
VB:
?customers.IndexOf(cust)
Thiswillreturn1,whichistheindexofthecurrentCustomerrecord,cust,inthe
collectioncustomers.Thiswillsavealotoftimewhentryingtofindthisobjectin
thedata.
4.ThedebuggeriscurrentlypausedonthelinethatcleansLastName,wherethe
NullReferenceExceptionoccurredandthereisayellowarrowonthebreakpoint.
Withyourmouse,dragtheyellowerroruptothelinethatcallsGetCustomers.We’re
currentlyattemptingtoanswerthequestionofwherethisvaluebecamenull.Iflucky,
wecanstopthisatthesourceandpossiblyfindabugwherethevalueisinadvertently
settonull.
5.PressF11tostepintotheGetCustomersmethod.VSwillnavigatetothefirstlineofthe
GetCustomermethod.
6.PressF10twicetoseewhatvaluesarebeingreturned.Thisexampleissosimplethat
youcanvisuallyseethedata.However,inrealscenarios,youwillprobablyberunning
codethatmakesthequerytoadatabase,orotherdatasource,andmightpreparethat
datainaformdigestiblebyanypotentialcallers.InChapter7,you’lllearnmoreabout
howtoperformdatabasequeries,butwewanttokeepthingssimplefornowsothat
youwon’tbedistractedbydetailsunrelatedtothepointofthisexercise,whichis
debugging.Therefore,weneedtoinspectthedatatoseeifitisthesourceofthenull
databytypingthefollowingcommandintotheImmediatewindow:
C#:
customers[1].LastName
VB:
?customers(1).LastName
178 MicrosoftVisualStudio2010:ABeginner’sGuide
Additionally,youcandrilldownintothecustomerscollectioninoneofthedebugging
windows,suchasAutos,Locals,orWatch,inspectingtheCustomerobjectatindex1.If
yourecallfromStep3intheprecedingsequence,theCustomerobjectwe’reinterested
inisatindex1.ThisresulttellsusthatLastNameforthisCustomerwassettonullat
thedatasourceandthereisnothingwecandotokeepitfrombeingsettonull;another
caseofbaddata.Ifyouseeatrend,youwouldbecorrect;nevertrustdatawhether
itcomesfromauseronthefrontendorfromthedatabaseonthebackend.Atthis
point,wehavealltheinformationweneedtofixtheproblemandmakesurewedon’t
accidentallycallmethodsonnulldata.
PressSHIFT-F5tostopdebugging.
7.Inthisexample,we’llfixtheproblembycheckingfornullbeforeusingavariableand
thenreplacingnullwithadefaultvalue.Commentoutthecontentsoftheforeachloop
andreplaceitwiththefollowingcode:
C#:
stringfirstName=string.Empty;
if(cust.FirstName!=null)
{
firstName=cust.FirstName.Trim();
}
stringlastName=
cust.LastName==null?
"":cust.LastName.Trim();
if(searchName==firstName)
{
Console.WriteLine(
"Found:{0}{1}",
firstName,
lastName);
customerFound=true;
}
VB:
DimfirstNameAsString=String.Empty
If(cust.FirstNameIsNotNothing)Then
firstName=cust.FirstName.Trim()
EndIf
DimlastNameAsString
Chapter6: DebuggingwithVisualStudio 179
Ifcust.LastNameIsNothingThen
lastName=""
Else
lastName=cust.LastName.Trim()
EndIf
If(searchName=firstName)Then
Console.WriteLine(
"Found:{0}{1}",
cust.FirstName,
cust.LastName)
customerFound=True
EndIf
Thiscodefixestheproblemtwodifferentways,givingyoumorethanonewayto
solvetheproblem,dependingonthestyleyouprefer.Inessence,thesolutionchecks
theFirstNameandLastNamepropertiestoseeiftheyarenull(NothinginVB).If
theyarenotnull,weknowthepropertieshavevalidstringsandaresafetoworkwith.
Otherwise,wereturnanemptystring.
InVB,youusetheIsandIsNotoperatorswhenworkingwithNothing,ratherthan
therespective==and!=forworkingwithC#null.Also,theVBIif,whichisthe
equivalentoftheC#ternaryoperator,evaluatesbothtrueandfalseexpressions,
resultinginaNullReferenceExceptionevenifthefalseconditiondoesn’texecute.
Therefore,theprecedingVBexampleusesthemoreverboseIfThenElsesyntax.
Thechoicetodefaulttoanemptystringisspecifictothisexampleonly.Inpractice,
you’llhavetolookatyourownsituationtoseeifitmakessensetouseadefaultvalue.
Forexample,thepresenceofanullvaluemightrepresentanerroneousconditionand
youmightprefertologtheconditionandnotallowtheusertocontinuewiththecurrent
operation.Anotherstrategymightbetoskipthisrecord,processingalltheothers,and
thenshowtheuseralistofrecordsthatweren’tprocessed.Youmightwanttofixthe
problemwithanyornoneoftheideasIhavehere,butmypointisthatyoushouldthink
aboutwhatworkingwithanullvaluemeanstoyourparticularsituationandnotthink
thattheonlywaytofixanullreferencebugisthewaywedidhere.
8.PressF5toruntheprogram.Itwillprovidethefollowingoutput:
Found:Jean
Victory!
180 MicrosoftVisualStudio2010:ABeginner’sGuide
Summary
Youarenowabletodebugcode.Thesection“Development-TimeCodeTools”explainedhow
toviewthestructureofyourcodeatdevelopmenttime.Youlearnedhowtosetbreakpoints
alongwiththemanyconditionsavailableforbreakpointcustomization.Thesection“Stepping
ThroughCode”explainedhowtonavigatethroughyourapplication,steppingintoandoutof
methodsandchangingtheexecutablelocationofyourapplication.Youcanalsoopenseveral
windowsandinspectthestateofyourapplication.Inparticular,youlearnedhowtousethe
DebugHistorywindowthatletsyouseethestateofanapplicationatvariousstagesofa
debuggingsession.
Inthenextchapter,wemigratefromapurefocusofworkingwithcodetousingthe
featuresofVSthatallowyoutoworkwith.NETtechnologies.Morespecifically,thenext
chaptershowshowVSmakesiteasytoworkwithdata.
Chapter 7
Working with Data
181
182 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● WorkonSQLServerDatabaseswithVisualStudio2010
● QueryDatawithLanguageIntegratedQuery(LINQ)
● UseLINQtoSQLtoQueryandManipulateSQLServerData
M ostoftheworkwedoeachdayinvolvesdata,andmostofthedataweworkwith
comesfromdatabases.Becauseoftheimportanceofdatainourapplications,this
chapterintroduceshowtoworkwithdatainVS.It’sveryimportanttolearntheconcepts
inthischapterbecauseitwillaffectalloftheworkyoudowhenprogramming.You’llalso
seemanyexamplesofworkingwithdatathroughouttherestofthisbook,underscoring
theimportanceofdatainsoftwareengineering.
Whileyou’refreetoworkwithanydatasourceyouwant,Microsofthasseveral
versionsofSQLServerfromfreeExpressversionstoEnterpriselevel.SinceSQLServer
ExpressshipswithVS,we’llusethatforalloftheexamplesinthischapterandtherest
ofthebook.Don’tworry;thedevelopmentexperienceforExpressissimilartoallother
versions,sowhatyoulearnwillbeapplicabletootherversionsofSQLServer.
Dataoperationsaresoimportantthatyoualsohavesupportintheprogramming
languagesforworkingwithdatacalledLanguageIntegratedQuery(LINQ).Youcanuse
LINQtoquerymanytypesofdatasources,whetheritisobjects,XML,orrelationaldata.
ThischapterwillshowyouhowtouseLINQforqueryingdatafromSQLServer.
View|ServerExplorerorpressingCTRL-ALT-S.ServerExplorer,showninFigure7-1,
allowsyoutoworkwithdatabases,servers,andSharePoint.Serversgiveyouaccess
tothevarioustypesofservicesformanaginganoperatingsystem,suchasEventLogs,
PerformanceCounters,andServices.Itisveryconvenienttobeabletoaccesstheseservices
inVSduringdevelopment.Forexample,ifyouneedtorestartanoperatingsystemservice,
youcandoitquickly.SharePointisoutofthescopeofthisbook,buttherelevantpartof
ServerExploreristheDataConnectionssectionatthetop,whichyoucanseeinFigure7-1.
TheDataConnectionssectionwillhavealistofdatabasesthatyoucanselectand
workwith.Initially,thelistwillbeemptyandyoumustaddconnectionsyourself,which
youcandobyright-clickingDataConnectionsandconfiguringthedatabasesettings.
Sincetheprocessofconnectingtoanexistingdatabaseissimilartothetaskforcreating
adatabase,I’llshowyouhowtocreateabrandnewdatabaseinstead,whichiscoveredin
thenextsection.
Creating a Database
Alloftheexamplesinthischapterwilluseadatabasethatwewillcreateinthissection.
Therefore,weneedtocreateadatabasetoworkwith.WithVSStandardandhigher,you
don’tneedexternaltoolstocreateasimpledatabasebecausethereisbuilt-insupportfor
gettingstarted.Thatsaid,thereareadvancedscenarioswhereadatabaseadministrator
wouldwanttousetheSQLServertoolstocreatethedatabasethemselves,meaningthat
youwouldonlywanttoconnecttothedatabasetheycreated.Formanycases,youcanjust
createthedatabaseyourselftogetstarted.
184 MicrosoftVisualStudio2010:ABeginner’sGuide
Tocreateadatabase,right-clickDataConnectionsinServerExplorer,andselect
CreateNewSQLServerDatabase.ThiswillshowtheCreateNewSQLServerDatabase
window,showninFigure7-2.
InFigure7-2,theservernameis.\sqlexpress.Thedotbeforethebackslashrepresents
thecurrentmachinename,andthesqlexpressisthenamefortheSQLServerExpress
database.Servernameswillvary,dependingonthelocationoftheserverandthename
giventothedatabaseserverinstance.Forexample,ifyouweredeployinganapplicationto
asharedWebhostingsite,theservernamewouldlooksomethinglikesql02.somedomain.
com,whichisestablishedbythehostingprovideryouareusing.
YourauthenticationoptionsincludeWindowsandSQLServer.Here,I’mchoosing
Windowsauthenticationbecauseit’sthesimplestoption.Thedatabasecreatedhereis
local,butyoumighthaveadatabasealreadycreatedonaserveratanotherlocation.
ThedatabaseonanotherservermighthaveaSQLlogin,whichisanothermethodof
authentication.
Afteraddingthedatabasename,clickOKtocreatethedatabase.AsshowninFigure7-2,
we’vecalledthisdatabaseMyShop,representinganapplicationthatsupportscustomerswho
orderproductsfromastore.You’llseethenewdatabaseunderDataConnectionsinServer
Explorer,similartowhatyouseeinFigure7-1.Nowyou’rereadytoaddtables.
Chapter7: WorkingwithData 185
Adding Tables
Thedatabaseitselfwillholddataforcustomers,orders,andorderdetailsthatweintroduced
intheprecedingchapter.Thedatawillbeheldintablesthatwe’llcreateinthissection.In
latersections,I’llshowyouhowtoperformCreate,Read,Update,andDelete(CRUD)
operationsonthisdata.Rightnow,you’lllearnhowtocreatethetables.
Tocreateatable,right-clicktheTablesbranchunderthedatabaseinServerExplorer
andselectAddNewTable;you’llseeaTableDesignersimilartoFigure7-3.Yourswon’t
havetheCustomerIDorNamecolumnsyet;that’scomingupnext.
TheTableDesignerallowsyoutoaddcolumnsandconfigurethedatatype(suchas
integer,date,float,orcharacter)andotherdetailsofeachcolumnandthetable.Figure7-3
showsatablewithtwocolumns,CustomerIDofdatatypeintandNameofdatatype
nvarchar(50).EnsurethatNullisuncheckedforeachcolumntoavoiderrorsincodethat
doesn’tcheckfornulllaterinthischapter.
NOTE
Databases, such as SQL Server, have their own type system, which doesn’t always
match the .NET type system perfectly. That said, there are types that match very well;
for instance, a SQL int is the same as a C# int or VB Integer. A SQL nvarchar(50)
can be matched with a C# string or VB String. However, the nvarchar is limited to
50 characters, or whatever length is specified in parentheses, but the C# string and VB
String don’t have a specified size. A full discussion of SQL types is out of scope, but you
should be aware that there are differences between SQL and .NET types.
TheCustomerIDhasaprimarykeysymbol,whichiscreatedbyright-clickingthe
columnandselectingSetPrimaryKey.Ifyouneededacompositekey(multiplecolumns
thatdefineakey),whichyoudon’tinthissimpleexample,youwouldpressCTRLandclick
eachcolumnthatbelongstothekeyandthenright-clickandselectSetPrimaryKey.
NOTE
When working with LINQ, which we discuss later in this chapter, it is absolutely
essential that you give every table a primary key.
Inadditiontosettingtheprimarykey,it’shelpfultomakethekeynumberauto-
incrementsothatitwillhaveauniquevalueforeveryrecordyouinsert.InFigure7-3,
youcanseethatCustomerIDisselectedandColumnPropertieshasscrolleddowntothe
IdentitySpecificationproperty.Bydefault,IdentitySpecificationiscollapsedandsetto
No.You’llneedtoexpandtheIdentitySpecificationpropertybyselectingthearrowon
theleft,andchangethevaluetoYesbyselectingthedrop-downarrowontherightofthe
“(IsIdentity)”setting,whichbydefaultisNo.ThiswillalsoenableIdentityIncrement,
whichspecifiesthenumbertoaddforeachnewrecord,andtheIdentitySeed,which
specifieswhatthefirstnumberwillbe.TheeffectofsettingIdentityIncrementisthatthe
firstrecordaddedtothetablewillhaveaCustomerIDwiththevalue1(IdentitySeed)and
subsequentrecordswillhaveaCustomerIDwiththevalues2,3,4,andsoon(Identity
Increment).ThevalueforCustomerIDineachrecordcreatesauniquevaluethatidentifies
therecordandmakesiteasytoprogramdataapplications.
Whenyou’redonecreatingthetable,clicktheSavebuttononthetoolbarandname
thetableCustomerwhenprompted.
YoucanadddatatotheCustomertablebyopeningthedatabaseinServerExplorer,
navigatetotheTablesfolderintheMyShopdatabase,right-clickCustomer,andselect
ShowTableData.You’llseeagridsimilartoFigure7-4whereyoucanentersome
customerdata.NoticethatyouneedonlytypeanameintheNamecolumn(replacingthe
wordNULL)anddonotneedtoenteravaluefortheCustomerID,sincewe’vemadethe
CustomerIDcolumnauto-increment.
Inadatabaseofanysophistication,youhavemultipletables.IntheMyShopdatabase,
aCustomerhasanOrder.So,createanewtablenamedOrder,showninFigure7-5,
thathasPrimaryKeyOrderID,adatetimefieldcalledOrderDate,andanintfieldcalled
CustomerID.
TheDescriptionintheColumnPropertiesfortheCustomerIDfieldsaysFKto
Customer.FKisanabbreviationforforeignkey,whichisusedtocreatearelationship
betweenaparenttableandachildtable.Thenextsectionexplainsmoreaboutwhat
aforeignkeyisandhowtocreateone.
canhavezeroormoreorders.Aforeignkeycanhelpmanagetherelationshipbetween
CustomerandOrder.
Themechanicsofcreatingaforeignkeyrelationshipisthatyouputtheforeignkey
columninthechildtable,Order,andhavetheforeignkeycolumnrefertotheprimary
keyoftheparenttable,Customer.Inthiscase,thereferenceismadesimplybymatching
theintegervalue;iftheIDnumberisthesameinbothtables,thentherecordsarerelated.
AsshowninFigure7-5,OrderdoeshaveaCustomerIDcolumn,oftypeint,andwewill
makethistheforeignkeythatwillrefertoCustomerIDprimarykeyinCustomer,shown
inFigure7-3.
TocreatethisforeignkeyrelationshipinVS,right-clicktheCustomerIDcolumnin
theOrdertableandselectRelationships.We’regoingtocreatetheforeignkeyrelationship
thatyouseeinFigure7-6.
Next,clickAdd,selecttheTablesAndColumnsSpecificproperty,andclickthe
ellipsesbuttonthatappearsonthefarrightofyourselection(theellipsesdoesnotappear
untilyoufirstclick“TablesAndColumnsSpecific”below“(General)”intheForeignKey
Relationshipsdialogwindow.ThiswillopentheTablesAndColumnswindowshownin
Figure7-7.
Intheprimarykeytabledrop-down,showninFigure7-7,selectCustomer,which
automaticallyselectstheprimarykey,CustomerID.(Note:Ifyoudon’tseethisbehavior,
checktoseethatyou’vesetyourprimarykeycolumnsandsavedthosetablechanges
asdescribedearlier.)Inthelist,underForeignKeyTableinFigure7-7,you’llinitially
seeOrderID,whichistheprimarykeyoftheordertable.SelectOrderIDandchangeit
toCustomerIDastheforeignkeycolumn.ClickOKtoexitandclickClosetofinalize
creationoftheforeignkeyrelationship.WhenyouclickSavetosavethenewforeign
keyrelationship,you’llseeawarningmessagesimilartoFigure7-8,listingthetables
participatinginthechange.SelectYestomakeyourchangestotheSQLServertables.
YoucanunchecktheWarnAboutTablesAffectedboxifyoudon’twanttoseethis
messageanymore,butthemessagedoesserveasasafetynettomakesureyoudon’t
accidentallysaveunintendedchangestoSQLServer,whichisanexternalproductto
VS2010.
Oncetheforeignkeyisinplace,youcanaddafewrecordstotheOrdertable,much
asyoudidwiththeCustomertable,butrememberthattheCustomerIDmustmatch
anexistingCustomerIDintheCustomertablebecauseoftheforeignkeyrelationship.
Forcingthechildtorefertoitsparentisgoodbecauseitmaintainstheintegrityofthe
database,demonstratingthevalueofaforeignkey.
190 MicrosoftVisualStudio2010:ABeginner’sGuide
TIP
Figure 7-7 shows an editable Relationship Name field. In many cases, you won’t
care what this name is because it follows a standard convention of FK_Child_Parent.
However, sometimes you have multiple relationships between the same tables, which
means that VS appends an incremental number to the end of the name. Thus, for
instance, the next foreign key relationship between the same two tables would be
FK_Child_Parent1. In those cases, it would be smart to plan ahead and change the
name to something meaningful so that you can later understand or quickly recall what
relationship rules the foreign keys are enforcing. To see what I mean by enforcing
rules, go ahead and enter a new record in the Order table, but enter an integer in the
CustomerID column that does not exist already in the Customer table, like 9999. Try to
save that record and then read the error message presented to you.
Workingwithmultipletables,youmightwanttohaveabetterfeelforthedatabase
structureandrelationships.Databasediagramscouldbehelpfulinthiscase.Tocreatea
databasediagram,right-clicktheDatabaseDiagramsfolderunderthedatabaseinServer
ExplorerandclickAddNewDiagram.ClickYeswhenyoureceiveaninformation
messagerequestingthecreationofobjectsfordatabasediagramming.IntheAddTable
window,presstheCTRLkeysothatyoucanselectmultiplerows,clicktoselecteach
table,andclickAdd.You’llseeanewdatabasediagramsimilartoFigure7-9(you
mayseeOrderappearaboveCustomerinyourdiagram,whichisfine;thepositionof
Chapter7: WorkingwithData 191
thesymbols—thekeyandtheinfinitysymbolattheendofthelineconnectingthetwo
tables—iswhatisimportant).
AsshowninFigure7-9,thedatabasediagramshowsyoutables,columns,and
relationships.Youcanusethiswindowtoaddnewtablesandrelationships.Whenyou
wanttocreateanewtable,right-clickthedesignsurface,selectAddTable,andusethe
VisualDesignertoconfigurethetable,asinpreviousexamples.Whatishelpfulwiththis
designeristheeaseinwhichforeignkeyrelationshipscanbecreatedascomparedtothe
methodweusedearliertoaccomplishthesamething.Tocreateaforeignkeyrelationship,
clicktheforeignkeycolumninthechildtable,dragthecarattotheparenttable,anddrop
thecaratontheprimarykeyoftheparenttable.Whenyou’refinishedwithcreatingthe
databasediagram,VSwillpromptforthediagramname;youcanreplywithanameof
yourchoiceandclickOKtosavethediagram.
Otherfeaturesofthedatabasediagramincludenavigation,printing,andmultiple
diagrams.Whenyouhaveadatabasediagramlargerthanthescreensize,clickthesymbol
withthefourarrowheadsatthelowerright-handcornerofthedatabasediagram,and
moveyourmousetoquicklynavigatethroughthedocument.Ifyouwantapermanent
192 MicrosoftVisualStudio2010:ABeginner’sGuide
copyofthediagram,right-clickandcopytoclipboardorselectFile|Print.Youcanalso
addmultiplediagramstotheDatabaseDiagramsfolder,allowingyoutohavemultiple
differentviewsforyourconvenience.
Inadditiontotablesanddiagrams,youcanadddatabaseviews,storedprocedures,
functions,synonyms,types,andassemblies.Mostofthesedatabaseitemsareforadvanced
scenarios,butit’simportantthatyouknowaboutstoredprocedures,whicharecoverednext.
CREATEPROCEDUREGetCustomers
AS
declare@cust_countint
select@cust_count=count(*)fromCustomer
if@cust_count>0
begin
select[Name]fromCustomer
end
return
Listing7-1declaresavariablenamed@cust_countandrunsaselectstatementto
assignthenumberofcustomers,count(*),to@cust_count.If@cust_countislargerthan0,
therearecustomersandthestoredprocedurequeriesforcustomernames.TeachingTSQL
(Microsoft’sdialectofSQL)syntaxisoutsidethescopeofthisbook,butyoucandownload
SQLServerBooksOnlineforfreeandpurchaseMcGraw-Hill’sMicrosoftSQLServer2008:
ABeginner’sGuide,FourthEditionbyDusanPetkovic(McGraw-Hill/Professional,2008)
togetstarted.
Chapter7: WorkingwithData 193
Toexecutethisstoredprocedure,right-clickthestoredprocedureinthedatabasein
ServerExplorerandclickExecute.You’llseeoutputsimilartothefollowingifthereare
recordsinthecustomertable:
Running[dbo].[GetCustomers].
Name
--------------------------------------------------
Meg
Joe
May
Norowsaffected.
(3row(s)returned)
@RETURN_VALUE=0
Finishedrunning[dbo].[GetCustomers].
Inadditiontoexecution,youcandebugthestoredprocedureinVS.Todebug,seta
breakpointonanylineinthestoredprocedure,right-clickthestoredprocedureinServer
Explorer,andselectStepIntoStoredProcedureorclickALT-F5.Ifyouneedmorehelp
debugging,visitChapter6forarefresheronVSdebuggingcapabilities.
optionsfoundafterclickingthearrowbuttontoexpandDatabaseToolsandthenselecting
TableAndDatabaseDesignersis“Preventsavingchangesthatrequiretablere-creation.”
VSwillnotallowyoutosaveaforeignkeychangetoexistingtables.However,by
unchecking“Preventsavingchangesthatrequiretablere-creation,”you’llbeabletosave
foreignkeychangestoanexistingtable.
AswithsomanyotherfeaturesofVS,thereareliterallydozensofdatabasesettings;most
areintuitiveifyoualreadyunderstandSQLServer.Otheroptionsdiffer,dependingonthe
versionofVSyouhave,andyourOptionsscreenmightnotlookthesameasFigure7-10.
Nowthatyouknowhowtocreatedatabases,tables,andstoredprocedures,you’llneed
toknowhowtouseyourdatabasefromcode.Therestofthischaptershowsyouhowto
useLINQtoworkwithdata.First,we’lllookatthebasicsyntaxofLINQthroughLINQ
toObjectsandthenfollowwithworkingwithSQLServerthroughLINQtoSQL.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
classCustomer
{
publicstringFirstName{get;set;}
publicstringLastName{get;set;}
}
classProgram
{
staticvoidMain(string[]args)
{
List<Customer>custList=newList<Customer>
{
newCustomer
{
FirstName="Joe",
LastName="Zev"
},
newCustomer
{
FirstName="May",
LastName="Lee"
},
newCustomer
{
FirstName="Meg",
LastName="Han"
}
};
varcustomers=
fromcustincustList
wherecust.FirstName.StartsWith("M")
selectcust;
foreach(varcustincustomers)
{
Console.WriteLine(cust.FirstName);
}
196 MicrosoftVisualStudio2010:ABeginner’sGuide
Console.ReadKey();
}
}
VB:
ClassCustomer
PropertyFirstNameAsString
PropertyLastNameAsString
EndClass
ModuleModule1
SubMain()
DimcustListAsNewList(OfCustomer)From
{
NewCustomerWith
{
.FirstName="Joe",
.LastName="Zev"
},
NewCustomerWith
{
.FirstName="May",
.LastName="Lee"
},
NewCustomerWith
{
.FirstName="Meg",
.LastName="Han"
}
}
Dimcustomers=
FromcustIncustList
Wherecust.FirstName.StartsWith("M")
Selectcust
ForEachcustIncustomers
Console.WriteLine(cust.FirstName)
Next
Console.ReadKey()
EndSub
EndModule
Chapter7: WorkingwithData 197
BoththeC#andVBexamplesfromListing7-2containsimilarLINQqueries.To
clarify,thefollowingexamplesshowboththeC#LINQquery:
varcustomers=
fromcustincustList
wherecust.FirstName.StartsWith("M")
selectcust;
andtheVBLINQquery:
Dimcustomers=
FromcustIncustList
Wherecust.FirstName.StartsWith("M")
Selectcust
ThecustomersvariableintheLINQqueriesreferencesanewcollectionthatholdsthe
resultofrunningtheLINQquery,whichcontainsallofthecustomerswherethefirstletter
oftheFirstNamepropertyistheletterM.Thefromclausespecifiestherangevariable
thatyouname,custisthenameIchose,andthecollectionobjecttoquery,custList,was
createdandpopulatedinthepreviouslineofcode.Therangevariableiswhatyouuseto
specifyparametersoftheLINQquery.Intheprecedingexample,weusethewhereclause
tofiltertheresultsofthequery.ThiswhereclausecallstheStartsWithmethodoneach
FirstNamepropertyofthecustrangevariabletospecifythefilter.
Theselectclausespecifiesthateachindividualcustomerobjectisreturnedintoour
newcustomerscollection,whichwedeclaredastypevar(DiminVB),whichmeansour
customersvariablewindsupbeingwhatevercollectiontypeisreturnedfromourLINQ
query.Thisalsomeansthattheresultingcustomerscollectionwillcontainzeroormore
Customertypeinstances,dependingonthefilterwespecifiedandwhetherourcustList
containedanyCustomerobjectsinthefirstplaceasaresultoftheSelectcustportionof
theLINQstatement.TheselectclauseforC#queriesisrequired,buttheselectclausefor
VBqueriesisoptionalandwillreturntherangevariableinstanceifomitted.
WhatourLINQstatementisessentiallysayinginEnglishis“Createanewcollection
objectandassignittoourvariablecustomers(wedon’treallycarewhattypeofobject
customersturnsouttobeaslongaswecanuseitlater),thengothrougheveryobjectin
ourpreviouslydefinedandloadedcustListcollection,selectingonlytheonesthathavefor
theirFirstNamepropertyastringthatbeginswiththeletterM,andignorealltherest,then
taketheonesthatmatchthisfilterandstuffthemintowhatevercollectionyoucreatedfor
meearlierthatyouassignedtomyvariablecustomers.”
198 MicrosoftVisualStudio2010:ABeginner’sGuide
VB:
Dimcustomers=
FromcustIncustList
Wherecust.FirstName.StartsWith("M")
SelectNewWith
{
.FullName=
cust.FirstName&""&
cust.LastName
}
ForEachcustIncustomers
Console.WriteLine(cust.FullName)
Next
InboththeC#andVBselectclausesyouseeanewstatement(NewWithinVB)that
definestheanonymoustype.Thenewanonymoustypehasasingleproperty,FullName,
thatisthecombinationofFirstNameandLastNameinCustomer,butthenewtypewill
Chapter7: WorkingwithData 199
onlyhaveaFullNameproperty.NoticehowtheforeachloopusestheFullNameproperty,
insteadoftheFirstNamepropertyfromListing7-2.Thebeautyofthisanonymoustype
isthatwedon’treallycarewhattypeofobjectisgeneratedforusbytheLINQquery,as
longasthatobjecthasthenewpropertyassociatedwithitthatwespecified,FullNamein
thiscase,whichitdoes.
Thevariable,cust,intheprecedinglistingisusedintwodifferentscopes:theLINQ
queryandtheforeachstatement.Althoughtheidentifier,cust,isthesame,thetwousages
areseparateinstances.Althoughyoumightnotusethesamepracticeinyourowncode,
Iwantedtodemonstratethissothatyoucanseethatrangevariables,suchascust,are
scopedtothequerytheyaredefinedin.
Anothernuanceoftheprecedingcodeisthatcust,intheforeachloop,isnottype
Customer.Rather,itisaninstanceoftheanonymoustypecreatedbytheprojection(select
clause)oftheLINQquery.Therefore,FullNameistheonlypropertyeachanonymous
typeinstance,cust,contains.
VB:
Dimcustomers=
FromcustIncustList
OrderBycust.FirstNameDescending
Selectcust
Theorderby(OrderByinVB)clausespecifiesthepropertiestosorton.Thisexample
sortsthelistbytheFirstNamepropertyindescendingorder.
ThiswasaquicktasteofwhatyoucoulddowithLINQ,andthereismuchmore.
Infact,IwroteanentirebookonthesubjecttitledLINQProgramming(McGraw-Hill/
Professional,2008).Theremainingsectionofthisbooktakeswhatyou’velearnedhere
andexpands,showingyoumoresamplesofLINQqueries.Thedifferencewillbethatyou
willbeworkingwithSQLServerdatainsteadofin-memoryobjects.
200 MicrosoftVisualStudio2010:ABeginner’sGuide
ToaddentitiestotheLINQtoSQLDesigner,openServerExplorer,selectadatabase,
andopentheTablesfolder.ThendraganddroptheCustomerandOrdertablesfromServer
ExplorertotheleftsurfaceoftheLINQtoSQLDesigner.YoucanseetheCustomerand
OrderclassesinFigure7-11,alongwithpropertiescorrespondingtothefieldsofeachtable
inthedatabase.
ThelinebetweenCustomerandOrderiscalledanassociation.Asyoumightguessfrom
readingthepreviousdiscussiononclassrelationships,theassociationdefinestherelationship
betweentwoclasses.Althougharelationshipbetweentablesisconstrainedbyaforeignkey
inachildthatreferstotheprimarykeyofthatchild’sparent,anassociationisthereverse
direction;itisapropertyofaparentclassthatreferstoallofthechildrenofthatclass.When
coding,youcanusethisassociationtonavigatebetweenparentandchildobjects.
NOTE
Features, such as the difference between foreign key relationships in relational
databases and associations in object-oriented code, are often referred to as an
impedance mismatch, a term taken from electrical engineering, between data and
objects. LINQ is designed to reduce the impedance mismatch by allowing you to work
with data from an object-oriented point of view, rather than doing all of the low-level
work yourself such as copying data records into data transfer objects, DTOs, that you
design and create.
OntherightpaneofFigure7-11,youcanseeaGetCustomersmethod,whichallows
youtocalltheGetCustomersstoredprocedure.Youcanputstoredprocedures,suchas
GetCustomers,ontothedesignsurfacebyopeningtheStoredProceduresfolderofthe
databaseinServerExploreranddragginganddroppingthatstoredprocedureontothe
rightpaneoftheLINQtoSQLDesigner.
Ifyourdatabasehasviewsandfunctions,youcanaddthemthesamewayasyoudid
forclassesandfunctionspreviously.Beforeshowingyouhowtousethesenewclasses
andviews,I’llshowalittlemoreaboutwhatyoucandowiththeLINQtoSQLDesigner.
ThedefaultzoomlevelfortheDesigneris100%,butyoucanchangethisbyright-
clicking,selectZoom,andselectazoomlevelpercent.Thismightbeusefulifyouwanted
ahigher-levelviewwhereyoucouldfitmoreobjectsontothescreenatonetime.
Ifyouright-clickandselectLayoutDiagram,VSwillautomaticallylayoutyour
diagramsothatclasseswithrelationshipscanphysicallyresideinthesameareawith
minimaloverlappingofassociationlines,afeatureIcallauto-layout.Afteryou’ve
performedauto-layout,youwillbeabletomanuallychangethelocationofclassesby
selectinganddraggingeachclasstoanewlocation,afeatureIcallmanuallayout.
TIP
Be careful of executing auto-layout after you have your layout the way you want. I tend
to perform an auto-layout after the first time working with the LINQ to SQL Designer
on a database. Then I follow up with manual layout to make working with classes even
easier. Using auto-layout after manual layout will result in a lot of lost work.
It’scommonindevelopmenttoaddnewtablestoadatabasethatyoualsowantin
theDesigner.Inthatcase,draganddropthetablesfromServerExplorerasyoudidfor
CustomerandOrderearlier.Ifatablechanges,youcanselectitscorrespondingclassin
theDesigneranddeletethatclassandthendraganddropthenewtableontothedesign
surface.AnyforeignkeyreferenceswillresultinassociationsontheDesignerifclasses
forbothtablesresideintheDesignertoo.
AnimportantpartofworkingwiththeDesignerisproperties.Right-clicktheDesigner,
selectProperties,andyou’llseethePropertieswindow,similartoFigure7-12.
LINQtoSQLgeneratesalotofcodeforyou,andthePropertieswindowallowsyouto
modifypartsofthatcodethroughtheCodeGenerationsection.Toseethissection,besure
yourPropertieswindowhasthe“Categorized”buttonselectednearthetopleftside,and
nottheAlphabetical“AZ”button.Youcanalsoseethedatabaseconnectionstring,which
iscreatedwhenyoudraggedanddroppedfromServerExplorertotheDesignerandsaved.
InadditiontopropertiesfortheDesigneritself,youviewpropertiesonobjectssuch
asclasses,associations,andmethods.Selecttheobjectyouwanttoworkwith,right-click
thatobject,andselectPropertiestoshowthePropertieswindowforthatobject.
Younowhaveadatamodeltoworkwith.Thefollowingsectionsshowyouhowto
workwiththisdatamodeltoquery,insert,update,anddeletedata.
C#:
usingSystem;
usingSystem.Linq;
namespaceLinqToSqlDemoCS
{
classProgram
{
staticvoidMain()
{
varmyShop=newMyShopDataContext();
varcustomers=
fromcustinmyShop.Customers
wherecust.Name!="Joe"
selectcust;
foreach(varcustincustomers)
{
Console.WriteLine("Name:"+cust.Name);
}
204 MicrosoftVisualStudio2010:ABeginner’sGuide
Console.ReadKey();
}
}
}
VB:
ModuleModule1
SubMain()
DimmyShopAsNewMyShopDataContext
Dimcustomers=
FromcustInmyShop.Customers
Wherecust.NameIsNot"Joe"
Selectcust
ForEachcustIncustomers
Console.WriteLine("Name:"&cust.Name)
Next
Console.ReadKey()
EndSub
EndModule
Andhere’stheoutputusingmydata:
Name:Meg
Name:May
Otherthantheobviousfactthatwe’renowgettingourdatafromarealdatabase,the
differencebetweenListing7-3andtheLINQtoObjectsexamplesyousawearlierarethat
youhavetousetheSystem.Linqnamespace(C#only),declaretheMyShopDataContext
datacontext,andqueryCustomersfromthedatacontext.InC#,theusingdirectivefor
theSystem.Linqnamespaceisrequired.Ifyouleftitout,thecompilerwillgiveyouthe
followingerrormessage:
“Couldnotfindanimplementationofthequerypatternforsourcetype‘System.
Data.Linq.Table<LinqToSqlDemoCS.Customer>’.‘Where’notfound.Areyoumissing
areferenceto'System.Core.dll’orausingdirectivefor‘System.Linq’?”
RememberthismessagebecauseanytimeyouaddanewfiletoaC#projectwhere
youarecodingLINQqueries,thiswillbeanindicationyouneedtoaddausingdirective
fortheSystem.Linqnamespace.
Chapter7: WorkingwithData 205
AdatacontextisthecodethatisgeneratedbyVSwhenyouruntheLINQtoSQL
itemwizard.TheMainmethodinstantiatesMyShopDataContext,whichisthedata
context.ThenamecamefromwhentheLINQtoSQLitemwizardranandyournamingof
the*.dbmlfile.
LINQtoSQLqueriesaremadewiththedatacontext,whichcontainsapropertythat
holdsacollectionoftheclasstypethatthepropertyisnamedafter,myShop.Customers
andmyShop.Ordersinthiscase.TheLINQqueryintheMainmethodusesthemyShop
datacontextinstancetoaccesstheCustomerscollectioninthefromportionofthequery.
NOTE
The LINQ to SQL provider uses pluralized data context properties. However, the
results are not perfect; for example, Deer becomes Deers, which is incorrect in English.
Additionally, pluralization is designed for English and will produce strange results in
languages other than English. If the pluralization generated by the LINQ of a class is
incorrect, you can either double-click the class name in the Designer or change the class
name via the Properties window.
ThissectionintroducedyoutowhatgoesintocreatingaLINQtoSQLquery,butyour
querieswilllikelyneedtoworkwithmultipletables,asdiscussedinthenextsection.
foreach(varcustOrdincustomers)
{
Console.WriteLine(
"Name:"+custOrd.Name+
"Date:"+custOrd.Date);
}
VB:
DimmyShopAsNewMyShopDataContext
Dimcustomers=
FromcustInmyShop.Customers
FromordIncust.Orders
SelectNewWith
{
.Name=cust.Name,
.Date=ord.OrderDate
}
ForEachcustOrdIncustomers
Console.WriteLine(
"Name:"&custOrd.Name&
"Date:"&custOrd.Date)
Next
Andhere’stheoutput:
Name:JoeDate:1/5/201012:00:00AM
Name:MayDate:10/5/201012:00:00AM
Name:MayDate:10/23/201012:00:00AM
ImaginethattheprecedingcodeissittingintheMainmethod,likewhatyousawin
Listing7-3.Thedifferentpartofthisquerythatmakesitaselectmanytypeofqueryis
thesecondfromclause.Considertheparent/childrelationshipbetweenCustomerand
Order,whichisrepresentedbycustandordinthisquery.Thesecondfromclauseuses
thecustinstancetospecifytheorderstoquery,whichwillbeallordersbelongingtoeach
customer.Theordinstancewillholdeachorderbelongingtoitsassociatedcust.Tomake
thisdatauseful,theprojectionisonananonymoustypethatpullstogetherthenameofthe
customerandthedateofthatcustomer’sorder.
Inthedatabase,IcreatedtwoordersforMay,oneorderforJoe,andzeroordersfor
Meg.Sincetherewasn’tanorderforMeg,youdon’tseeanyitemsfromMeginthe
output.Later,I’llshowyouhowtoaddaparentrecord,evenwhenthatparentrecordhas
nochildrecords.
Theselectmanyqueryisfineforsimplequeriesbutbecomeshardertouseinmore
complexqueries.Inthiscase,ajoinqueryemergesasaneasieroption.Likeaselectmany
Chapter7: WorkingwithData 207
query,ajoinquerywillcombinetwotablesthathavematchingkeys.Here’sanexampleof
ajoinquerythataccomplishestheexactsametaskastheprecedingselectmanyquery:
C#:
varmyShop=newMyShopDataContext();
varcustomers=
fromcustinmyShop.Customers
joinordinmyShop.Orders
oncust.CustomerIDequalsord.CustomerID
selectnew
{
Name=cust.Name,
Date=ord.OrderDate
};
foreach(varcustOrdincustomers)
{
Console.WriteLine(
"Name:"+custOrd.Name+
"Date:"+custOrd.Date);
}
VB:
DimmyShopAsNewMyShopDataContext
Dimcustomers=
FromcustInmyShop.Customers
JoinordInmyShop.Orders
Oncust.CustomerIDEqualsord.CustomerID
SelectNewWith
{
.Name=cust.Name,
.Date=ord.OrderDate
}
ForEachcustOrdIncustomers
Console.WriteLine(
"Name:"&custOrd.Name&
"Date:"&custOrd.Date)
Next
Thedifferencebetweenthisqueryandtheselectmanyisthatthereisajoinclause
insteadofasecondfrom.Thejoinidentifiesarangevariable,ord,andoperatesonthe
Orderspropertyofthedatacontext.Youalsomustspecifywhichkeysofthetable
join,mentioningtheparentfirst,cust.CustomerID,andthenthechild,ord.CustomerID.
Remembertousetheequalskeywordbecausetheequalityoperatorwillnotwork.
208 MicrosoftVisualStudio2010:ABeginner’sGuide
TheselectmanyandjoinclausesaresynonymouswithSQLinnerjoinsbecausethere
mustbeaforeignkeyinachildtablethatmatchesaparentintheparenttablebeforeany
recordsfortheparentwillbereturned.Toaddresstheissueofneedingtogetparentsthat
don’thavechildren,youmustperformaleftouterjoin.Toperformtheequivalentofa
SQLleftouterjoininLINQ,youmustuseastandardoperatorcalledDefaultIfEmpty.The
followingquerygetsarecordforallcustomers,regardlessofwhethertheyhaveordersornot:
C#:
varmyShop=newMyShopDataContext();
varcustomers=
fromcustinmyShop.Customers
joinordinmyShop.Orders
oncust.CustomerIDequalsord.CustomerID
intocustomerOrders
fromcustOrdincustomerOrders.DefaultIfEmpty()
selectnew
{
Name=cust.Name,
Date=custOrd==null?
newDateTime(1800,1,1):
custOrd.OrderDate
};
foreach(varcustOrdincustomers)
{
Console.WriteLine(
"Name:"+custOrd.Name+
"Date:"+custOrd.Date);
}
VB:
DimmyShopAsNewMyShopDataContext
Dimcustomers=
FromcustInmyShop.Customers
GroupJoinordInmyShop.Orders
Oncust.CustomerIDEqualsord.CustomerID
IntocustomersOrders=Group
FromcustOrdIncustomersOrders.DefaultIfEmpty()
SelectNewWith
{
.Name=cust.Name,
.Date=IIf(custOrdIsNothing,
NewDateTime(1800,1,1),
custOrd.OrderDate)
}
Chapter7: WorkingwithData 209
ForEachcustOrdIncustomers
Console.WriteLine(
"Name:"&custOrd.Name&
"Date:"&custOrd.Date)
Next
Andtheoutputis
Name:MegDate:1/1/180012:00:00AM
Name:JoeDate:1/5/201012:00:00AM
Name:MayDate:10/5/201012:00:00AM
Name:MayDate:10/23/201012:00:00AM
ForC#,theleftouterjoinisaccomplishedthesamewayasajoinexceptfortwo
additionallines:theintoclauseandthesecondfromclause.ForVB,theleftouter
joinisthesameasthejoinexceptforthreelines:theIntoclause,thesecondFrom
clause,andtheGroupkeyword.Theintoclausespecifiesanidentifierthatisusedby
thefromclause.Inthefromclause,DefaultIfEmptywillreturnthedefaultvaluefor
thecontinuationvariabletype.Intheprecedingexample,thecontinuationvariableis
customerOrderswhosetypeisOrder.SinceLINQtoSQLtypesareclassesandOrder
isaclassfromtheOrdersentitycollection,thedefaultvalueisnull(NothinginVB).
NoticehowIenhancedtheprojectionwithaternary(immediateifinVB)operatorto
controlwhatvalueisreturnedwhentheparentdoesn’thaveachild.Whenperforming
aleftouterjoin,makesureyoucomparethevalueagainstitsdefaultvaluetodetermine
iftheparentdoesn’thaveachildandensurethatvalidvaluesareset.Notonlydoesthe
precedingexampledemonstratehowtocheckforadefaultvalue,butitalsoshowsthat
youcanuseexpressionsinyourprojections.
InadditiontoLINQqueries,youcancallstoredprocedures.Asyoumayrecallfrom
thepreviousdiscussiononworkingwiththeLINQtoSQLDesigner,Idescribedhowto
draganddropastoredprocedurefromServerExplorertothedesignsurface.Addingthe
storedproceduretothedesignsurfacealsoaddedamethodtothedatacontext.Here’s
howtousethatmethod:
C#:
varmyShop=newMyShopDataContext();
varcustomers=myShop.GetCustomers();
foreach(varcustincustomers)
{
Console.WriteLine("Name:"+cust.Name);
}
210 MicrosoftVisualStudio2010:ABeginner’sGuide
VB:
DimmyShopAsNewMyShopDataContext
DimcustomersAsIEnumerable=
myShop.GetCustomers()
ForEachcustOrdIncustomers
Console.WriteLine("Name:"&custOrd.Name)
Next
Andhere’stheoutput:
Name:Meg
Name:Joe
Name:May
JustcallmyShop.GetCustomersandyou’llreceiveacollectionofCustomerobjects.
TherearemanymoreadvancedscenariosthatyoucanhandlewithLINQ,butthis
isjustabeginner’sguide.However,younowhaveasolidbaseofquerytechniquesthat
willgetyoustarted.Inadditiontoqueryingadatabase,you’llneedtoperforminsert
operations,whichisnext.
TIP
LINQ to SQL generates SQL (Structured Query Language) statements to send to the
database for your queries. If you would like to see the generated SQL, set a breakpoint
on the line after the query and run the program with debugging. When you hit the
breakpoint, hover over the variable holding query results and you’ll see the SQL
statement.
VB:
FunctionInsertCustomer()AsInteger
Dimcust=NewCustomerWith
{
.Name="Jim"
}
DimmyShopAsNewMyShopDataContext
myShop.Customers.InsertOnSubmit(cust)
myShop.SubmitChanges()
Returncust.CustomerID
EndFunction
Asshownhere,eachcollectionproperty,suchasCustomers,hasanInsertOnSubmit
methodthattakesanobjectofthecollection’stype,Customerinthiscase.Don’tforget
tocallSubmitChanges,orelseyouwon’tseeanychangestoyourdata.Thenextsection
discussesupdates.Oncetheinsertexecutes,withSubmitChanges,thenewobject,cust,
willbeupdatedwiththenewCustomerID,whichyoureadandreturntocallingcode.
VB:
SubUpdateCustomer(ByValcustIDAsInteger)
DimmyShopAsNewMyShopDataContext
Dimcustomers=
FromcustInmyShop.Customers
Wherecust.CustomerID=custID
Selectcust
DimfirstCustAsCustomer=
customers.SingleOrDefault()
If(firstCustIsNotNothing)Then
firstCust.Name="James"
EndIf
myShop.SubmitChanges()
EndSub
InthepreviousqueriesforthecustomerwhosenamewasJim,changetheobjectto
Jamesandsaveschanges.ThecalltoSingleOrDefaultwasnecessarybecausetheresult
ofaLINQtoSQLqueryisacollection,butweonlywantthefirstoronlyrecordreturned.
ThereisalsoanoperatormethodnamedSingle,butusingSingleOrDefaultisfavorable
becauseitreturnsadefaultvalueifnorecordsarereturned,whereasSinglewillthrowan
exception.Thecodeusesanifstatementtoprotectagainstthepossibilityofanexception;
otherwise,thecodewouldthrowaNullReferenceExceptionwhenfirstCustisnull(Nothing
inVB)andthecodetriestoaccesstheNamepropertyofanullobject.Remembertocall
SubmitChanges;otherwisetheupdateswon’tbemade.
Youcannowquery,insert,andupdate.Yourfinalskilltolearnisdeletingdata.
CustomerfirstCust=customers.SingleOrDefault();
if(firstCust!=null)
{
myShop.Customers.DeleteOnSubmit(firstCust);
}
myShop.SubmitChanges();
}
VB:
SubDeleteCustomer(ByValcustIDAsInteger)
DimmyShopAsNewMyShopDataContext
Dimcustomers=
FromcustInmyShop.Customers
Wherecust.CustomerID=custID
Selectcust
DimfirstCustAsCustomer=
customers.SingleOrDefault()
If(firstCustIsNotNothing)Then
myShop.Customers.DeleteOnSubmit(firstCust)
EndIf
myShop.SubmitChanges()
EndSub
Thisexampleissimilartotheupdateexamplethatdidaqueryandthenacallto
SingleOrDefaulttogetareferencetotherequestedobject.Youthenusethecollection
property,Customersinthiscase,tocalltheDeleteOnSubmitmethod.Youneedthe
checkfornull(NothinginVB),oryou’llreceiveanArgumentNullExceptionwhen
DeleteOnSubmitexecutesandthefirstCustargumentisnull(NothinginVB).Remember
tocallSubmitChanges;otherwise,youwon’tdeletetherecord.
Afinalnoteontheprecedingthreesections.Thecoderunsinaninsert,update,and
deletesequence.Noticehowtheinsertmethodsreturnanint,whichistheCustomerID.
Wheneveryouperformaqueryfromadatabase,you’lloftenwanttogettheIDfieldfor
therecordatthesametime.ThereasonisthattheIDisuniquetothatonerecordand
youcanperformsubsequentactionswiththeID.Boththeupdateanddeletemethodsin
precedingexamplesacceptedanintparameterthatwasusedtoperformadatabaselookup
oftherecord.Again,usingtheIDguaranteesthatwe’llonlyreturnonerecord,whichis
alsowhyIwasconfidentincallingSingleOrDefault.Sincethischapterisaboutdata,I
purposelydon’tshowyouhowtheprogramhandlesthatID.However,you’llseeIDsbeing
214 MicrosoftVisualStudio2010:ABeginner’sGuide
usedinmultiplelaterchaptersthatshowyouhowtobuilduserinterfaces.Payattentionto
howtheUIcodeholdsontoIDsandthenusesthemwhencallingcodethatinteractswith
thedatabase.You’llseemanydifferentexamples,butmostoftheexamplesthatyousee
andthenuseinyourownprogramswillbevariationsofwhatyou’velearnedhere.
Summary
ThischaptershowedyouhowtoworkwiththeVSdatabasetools.Youcancreatetables,
relationships,andstoredprocedures.Thesection“QueryingObjectCollectionswith
LINQ”helpedyouunderstandbasicLINQqueries.YoucannowuseLINQtoSQL,
settingupadesignerwithclassesandmethods.Additionally,youcancreate,read,update,
anddeletedatawithLINQtoSQL.
ThischapterusedConsoleapplicationstoshowyouhowtoworkwithdata.Thiswas
tohelpyouconcentrateondataaccessexclusively,minimizinganyotherdistractions.
However,realapplicationsrequiregraphicaluserinterfaces(GUIs).Remainingchapters
ofthisbookwillshowyouhowtocreateGUIapplicationsthatconsumedata,givingyou
manymoreexamplesofhowLINQtoSQLworksinanapplication.Thenextchaptergets
youstartedinGUIdevelopmentwithWPF.
Part III
Building Programs
with VS 2010
This page intentionally left blank
Chapter 8
Building Desktop
Applications with WPF
217
218 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● PerformScreenLayout
● UseControls
● WorkwithDataintheUI
W indowsPresentationFoundation(WPF)isa.NETtechnologyforbuildingdesktop
applications.TheresultofbuildingaWPFapplicationisan*.exefilethatyoucan
rundirectlyonyourcomputerordeployandrunonanyothercomputerthathas.NET
installed.WithWPF,youcanaddagraphicaluserinterface(GUI),pronounced“Gooey,”
thatmakesiteasierforuserstoworkwithyourprogram.Thischapterwillshowyouhow
tolayoutascreeninWPFandexplainthecontrols,suchasButtonandTextBox,thatyou
canplaceonthescreen.You’llalsolearnhowtocaptureeventsoffcontrols,allowingyou
toaddcodethatrunsbasedonuserinput.Sincemostapplicationsworkwithdata,this
chapterbuildsonwhatyoulearnedinChapter7andshowshowtobinddatatocontrolsin
theGUI.
ThischapterwillshowyouhowtobuildaWPFGUIwiththeVSDesigner,but
sometimesyoumustworkatalowerlevelandmanipulatetheXAML,pronounced
“Zammel,”thatdefinestheGUI.XAMLisanXMLformatthatWPFandSilverlight
usetodefineaGUI.Therearetwoappendixesinthisbookthatwillhelpyougetupto
speedinXAML:AppendixA,“IntroductiontoXML,”andAppendixB,“Introductionto
XAML.”Ifyouaren’tfamiliarwithXML,startwithAppendixA.However,ifyouhave
agoodgraspofbasicXMLsyntax,gostraighttoAppendixB.I’lltrytoexplainWPFin
awaythatanyXAMLyouseecanbeunderstoodinitscontext,butyoumightwantto
reviewtheappendixestoavoidanyconfusion.Onceyou’refamiliarwithXAML,youcan
returnhereandstartwiththenextsection,whichexplainshowtostartaWPFproject.
solutionname.I’mnamingtheexamplesinthechapterasMyShoptocontinuetheidea
ofcustomerswhobuyproductsthatstartedinChapter7whendiscussingdata.Figure8-1
showsthenewWPFapplicationinVS,includingaToolbox,aDesigner,andaSolution
Explorer.TheToolboxcontainscontrols,whichareuserinterface(UI)elements,suchas
ButtonandTextbox,thatyoucandraganddropontotheDesigner.
NOTE
There is another .NET technology, Windows Forms, for creating desktop applications.
This book doesn’t discuss Windows Forms because it’s an older technology. The way
forward for desktop application development is WPF, and the intention of this book is to
help guide you in a direction most beneficial to you.
TheDesignerallowsyoutolayouttheUIoftheapplication;itisdividedintoDesign
onthetopandXAMLonthebottom.TheDesignsurfaceallowsyoutovisuallywork
withcontrolsandlayoutsofthosecontrols.TheXAMLeditorallowsyoutoworkwith
theXMLrepresentationofthecontrolsonthedesignsurface.TheDesignandXAMLare
interrelatedbecauseachangeinonecausesachangeintheother.Forexample,ifyouadd
aButtontotheDesign,you’llseetheXMLrepresentationofthatButtonintheXAML.
Similarly,ifyouaddaTextBoxelementtotheXAML,you’llseethevisualrepresentation
ofthatTextBoxinDesign.
Youhavevariouscontrolsformanipulatingthewindows.BothDesignandXAML
havezoomcontrols.ThezoomtoolonDesignisasliderintheupper-leftcorner,and
zoomforXAMLisadrop-downcontrolinthelower-leftcorner.Youcanalsozoomby
clickingeitherDesignorXAMLandmovingthemousewheel.Attheupperrightofthe
XAMLeditor(bottomrightoftheDesignsurface),youcanswitchbetweenhorizontaland
verticalsplitsofthewindoworclickthechevrontocollapsetheXML.Thesplittericon
belowthechevronallowsyoutosplittheXAMLeditorintotwoifyoudragitdown.The
up-downarrowbetweentheDesignandXAMLtabsallowsyoutoswitchsidessothat
eachpanelshowswheretheotherwas.Locatingthecaratinthemiddleoftheseparator
betweenDesignandXAMLallowsyoutoresizeeachwindow.
Understanding Layout
Alayoutdefineshowyoucanpositionandsizecontrolsonascreen.WPFwindowsand
controlshaveaContent(canoccasionallybecalledsomethingelse)propertythataccepts
asinglecontrol.Insomecases,suchasaButtoncontrol,thecontentcanbetext.However,
manysituationscallfortheabilitytolayoutmultiplecontrols.Thissectionconcentrates
onperforminglayoutinwindows,andaWindowhasaContentpropertythataccepts
onlyonecontrol;thatonecontrolshouldbealayoutcontrol,whichisthesubjectofthis
section.
WPFincludesseverallayoutcontrols,includingGrid,StackPanel,DockPanel,
WrapPanel,andCanvas.Bydefault,VSwillgenerateawindowwithaGridasthelayout
control.However,youarefreetoreplacetheGridwithanyotherlayoutcontrolthatsuits
yourneeds.Thissectionwillshowyouhowtouseeachofthesecontrols.
Grid Layout
WheneverstartinganewWPFproject,VSaddsaGrid.AGridisalayoutcontrolthat
allowsyoutocreateasetofrowsandcolumnsthatholdothercontrols.Youcanaddrows
andcolumnstoaGridthroughtheVisualDesignerbyclickinginthemiddleofawindow
indesignview.Figure8-2showsacolumnbeingaddedtoaGrid.
Thethinverticallineinthemiddleofthewindowisanewborderbetweentwocolumns.
Afterclickingthewindow,you’llseetwothickbordersontheleftandtopofthewindow.
Whileyouhoveroverthetopborder,VSdrawsaverticallinethatmovesleftandrightas
yourunyourmousealongthetopborder.Youcandothesamewiththeleftborder,adding
rowstotheGrid.ThisisaveryquickwaytoaddrowsandcolumnstoaGrid.
Chapter8: BuildingDesktopApplicationswithWPF 221
ThearrowintheGridborderallowsyoutorepositionthecolumnorrowborder.
YoucanremovethecolumnorrowborderbyselectingthearrowintheGridborderand
draggingthearrowoffthewindow.
CAUTION
Don’t press the DELETE key when you have a border selected. You’ll accidentally delete
your Grid, which you might have spent some time on. If you want to remove a column
or row, grab the arrow for the border you want to remove and drag the border off the
window.
Onceyou’vecreatedrowsandcolumns,youcanaddfurthercustomizationsthat
definehowmuchspacethecolumnorrowcantake.Therearethreesizingcustomizations:
fixed,weighted,andauto.Toseteachoftheseoptions,hoveroverthecolumnorrow
borderandVSwilldisplayasizingpanel,asshownovertheleftcolumndesignborderin
Figure8-3.
Thediamondiconontheleftmeansfixed,wherethesizewillstaythesame.Theasterisk
iconinthemiddleisaweightedproportion,wherethesizestaysthesameinrelationto
theothercolumns.Therightmosticonisauto,meaningthatthesizewillvaryaccordingto
222 MicrosoftVisualStudio2010:ABeginner’sGuide
whateverspaceremainsaftertheothercolumns’sizesareset.Afteryou’veaddedcontentto
yourGrid,youcanusethesesizingoptionstoexperimentwiththelayoutthatyouwant.
OnethingtonoticeinFigure8-3isthenumberintheGridborderforeachrowand
column.Thesenumberstellyouthesizeinpixelsforeachrowandcolumntheyappear
upon.
Figure8-3alsoshowsthePropertieswindowontheright,whereyoucanselectand
customizetheColumnandRowcollections.
TruetothepurposeoftheGrid,Figure8-3showscontrolsthathavebeenaddedto
theGrid,placedineachcelloftheGrid.AnotherpopularlayoutcontrolisStackPanel,
discussednext.
StackPanel Layout
TheStackPanelisidealforwhenyouwanttolayoutcontrolseachontopoftheother,like
astack.YoucanuseaStackPanelbydraggingtheStackPanelcontrolfromtheToolbox
ontothedesignsurface.IfyouwanttousetheStackPanelasyourprimarylayout,youcan
Chapter8: BuildingDesktopApplicationswithWPF 223
selectthegrid,whichisaddedbydefaulttoanewproject,anddeletetheGrid.Figure8-4
showsaStackPanelthatcontainsmultiplebuttoncontrols.
InFigure8-4,itdoesn’tmatterwhereyoutrytolaythebuttons—theStackPanelwill
alwayslaythemoutoneaftertheother.Inadditiontoverticallayout,theStackPanelcan
layoutcontrolshorizontally.JustchangetheOrientationproperty,shownintheProperties
windowinFigure8-4,toHorizontal.Next,you’lllearnhowtodockcontrolstothesides
ofacontainer.
DockPanel Layout
You’veseenhowVSallowsyoutodockwindowswithinthebordersoftheapplication.
Thishelpsyouorganizeyourscreensothatyoucanusemanytoolsatonetime.Youcan
layoutyourcontrolsthesamewaywiththeDockPanelcontrol.
GetstartedbydragginganddroppingaDockPanelcontrolfromtheToolboxtothe
Windowinthedesignsurface.YoumightwanttodeletethedefaultGridfirst.Also,the
DockPanelinitializeswithaHeightandaWidth,whichyou’llprobablywanttoremove
byselectingtheDockPanel,openingthePropertieswindow,andclearingtheHeightand
224 MicrosoftVisualStudio2010:ABeginner’sGuide
Widthproperties.RemovingtheHeightandWidthpropertiesallowstheDockPanelto
expandandcovertheentirewindow.Figure8-5showsaDockPanelwithLabelcontrolsin
eachdockingposition.
EverytimeyoudraganddropacontrolontothedesignsurfaceofaDockPanel,the
controlwilltakethecenterpositionbydefault.Tospecifywherethecontrolshoulddock,
openthePropertieswindowandsettheDockLayout.Dockproperty.Whenyouaddanew
control,thenewcontrolwillbecomethecentercontrolandtheothercontrolwilldockto
thesideoftheDockPanelyouspecifiedintheDockproperty.Thenextlayoutcontrolis
WrapPanel.
WrapPanel Layout
Whenevercontrolsshouldnaturallyfolloweachotherinsequenceandcontinuewrapping
onnewlines,youcanuseaWrapPanel.Examplesofwhenthisisusefulcouldbewhen
addingcontrolsthatcontaintextandit’susefultoviewthecontrolsinsequence.Figure8-6
showsseveralCheckBoxcontrolsinaWrapPanel.
Chapter8: BuildingDesktopApplicationswithWPF 225
Figure8-6demonstrateshowyoucanlayoutagroupofcontrolstofillanavailable
space.InthecaseoftheCheckBoxcontrols,theOrientationoftheWrapPanelissetto
Vertical(thedefaultisHorizontal).WhenthenumberofCheckBoxcontrolsfillsthe
verticalcolumn,remainingCheckBoxeswraptothenextcolumn.Becausethesizesofthe
CheckBoxcontrolsarethesame,youhaveauniformlayout,whichiseasierthantrying
todothesamethingwithaGridorotherlayoutcontrol.Thefinallayoutcontrolwe’ll
discussistheCanvas,whichisnext.
Canvas Layout
Therearetimeswhenyoumightwanttoperformexplicitlayoutofcontrols.Ifyou
werebuildingadiagrammingapplicationoradrawingprogram,orifyoujustwantedto
explicitlyspecifythelocationofcontrols,theCanvaslayoutwillworkfine.Figure8-7
showssomecontrolsonaCanvaslayout.
TheRectangleandEllipsecontrolsweredraggedanddroppedfromtheToolboxonto
theCanvascontrol.NoticetheCanvas.Left,Canvas.Top,Width,andHeightpropertiesinthe
Propertieswindow,demonstratingtheabsolutepositioningoftheselectedEllipsecontrol.
226 MicrosoftVisualStudio2010:ABeginner’sGuide
Nowthatyouknowhowtousethelayoutcontrols,thenextsectiontakesacloserlook
atWPFcontrolsingeneral,givingyoutipsonhowtousetheminyourapplication.
You’llfindalloftheavailablecontrolsontheToolbox,dividedintopanelswherethe
toppanelisCommonWPFcontrols,whichmakesiteasytofindthecontrolsyouusethe
most.TheAllWPFControlstabincludesthecompletelistofWPFcontrols.
You’veseenhowtheDesignercanbeusedintheprecedingsection,whichdiscussed
layoutcontrols.YoucanopentheDesignerbydouble-clickinga*.xamlfileinSolution
Explorer.ToaddacontroltotheDesigner,selectthecontrolintheToolboxanddragthe
controlontotheDesigner.Figure8-8showsaButtonthathasbeendraggedanddropped
ontotheDesigner.
InFigure8-8,youcanseetheToolboxwiththeButtoncontrolselected.TheDesigner
showsaButtoncontrolthathasbeendraggedanddropped.Inpractice,you’llbeadding
thiscontrolintosometypeoflayoutcontrolsothatyoucanpositionitappropriatelyon
thescreen.
BelowtheDesigner,theButtoncontrolappearsintheXAMLforthiswindow.If
youareuncomfortablelookingatXAML,youcanreviewAppendixBasarefresher.
TheattributesoftheButtoncontrolintheXAMLmatchthepropertiesintheProperties
window.
TIP
It’s important to learn how to quickly build UIs using the Visual Designer because
it enhances productivity. However, it’s also important to be able to read the XAML
associated with a window because as you move beyond the beginner content of this
book, you’ll find scenarios where the Designer alone might not allow you to control
every nuance of your visual presentation. A good way to move forward is to experiment
on your own by adding each of the controls from the Toolbox to the Designer and then
examine the generated XAML.
Setting Properties
ThePropertieswindowshowsallofthewaysthatyoucanconfigureacontrol.Forbutton
controls,you’llwanttochangetheContentpropertytomakethetextonthebuttonmake
sense.Inthisexample,we’llimaginethatthepurposeofthebuttonistoallowauserto
createaneworderforacustomer.Therefore,settheContentpropertytoNewOrder.
Handling Events
Inadditiontoproperties,youcanhandlecontroleventsviatheEventstabatthetopofthe
Propertieswindow.Figure8-9showsthecontentsoftheEventstab.
Controlshaveliterallydozensofeventsthatallowyoutomanagetheirbehaviorinthe
application.Someevents,likeClick,arecommonlyused,whileotherevents,suchasDrag
Over,onlysupportuniquescenarioslikedraganddropthatyoumightnotevercareabout.
Tohandleanevent,youcandouble-clickanyoftheeventsinthePropertieswindowand
VSwillwireupthateventtoahandlermethodwithadefaultname.
SincetheClickeventissocommon,I’llshowhowitworks.Youcanimplementa
handlerfortheClickeventbydouble-clickingtheClickeventinthePropertieswindow
Eventstab.Whenyoudouble-click,VSopensafilenamedMainWindow.xaml.cs,
assumingthewindowyou’reworkingwithisnamedMainWindow.xaml.MainWindow
.xaml.csiscalledacode-behindfileandiswhereyoucanaddeventhandlers.VSalso
createsaskeletonmethodinMainWindow.xaml.csthathandlestheButtonClickevent,
showninListing8-1.
Chapter8: BuildingDesktopApplicationswithWPF 229
TIP
Controls have default events. The significance of default events is that if you double-click
the control in the Designer, VS will generate an event handler for the default event. To
be more specific, consider the Button control whose default event is the Click event. If
you double-click the Button control in the Designer, VS will generate an event handler
for the Click event.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Windows;
usingSystem.Windows.Controls;
usingSystem.Windows.Data;
usingSystem.Windows.Documents;
usingSystem.Windows.Input;
usingSystem.Windows.Media;
usingSystem.Windows.Media.Imaging;
230 MicrosoftVisualStudio2010:ABeginner’sGuide
usingSystem.Windows.Navigation;
usingSystem.Windows.Shapes;
namespaceControlsCS
{
///<summary>
///InteractionlogicforMainWindow.xaml
///</summary>
publicpartialclassMainWindow:Window
{
publicMainWindow()
{
InitializeComponent();
}
privatevoidbutton1_Click(objectsender,RoutedEventArgse)
{
}
}
}
VB:
ClassMainWindow
PrivateSubButton1_Click(
ByValsenderAsSystem.Object,
ByValeAsSystem.Windows.RoutedEventArgs)
HandlesButton1.Click
EndSub
EndClass
TheClickeventhandler,justcreated,isthehighlightedmethod,button1_Click
(Button1_ClickinVB),thatyouseeinListing8-1.Wecovereddelegatesandeventsin
Chapter4,whichyoucanreviewforabetterunderstandingofhowthismethodhandles
theClickevent.NoticehowtheVBcodeshowsanotherwaytohandleeventsinVB,by
explicitlyspecifyingHandlesButton1.Click.Essentially,whenauserclicksonthebutton
namedbutton1,thishandlerwillbecalled.Thisillustratestheconceptofevent-driven
programming,whereyouwritehandlers,suchasbutton1_Click,thatruncodeaccording
Chapter8: BuildingDesktopApplicationswithWPF 231
touseractions.Inadditiontocreatingtheeventhandlerinthecode-behind,VSaddsthe
methodnametotheClickeventontheEventstabinthePropertieswindow,shownin
Figure8-9.
Inadditiontocreatingthehandlermethodandassigningthemethodnameinthe
Propertieswindow,VSaddsthemethodasanattributetotheButtoncontrolinthe
XAML,shownhere.TheXAMLisindependentofprogramminglanguageandworksthe
sameregardlessofwhetheryouarecodinginC#orVB:
<ButtonContent="Button"Height="23"
HorizontalAlignment="Left"Margin="76,43,0,0"
Name="button1"VerticalAlignment="Top"Width="75"
Click="button1_Click"/>
Noticetheconventionbeingusedonthemethodname,controlName_Event.The
controlNamepartcomesfromthenameofthecontrol,whichisbutton1,andtheeventis
theeventbeinghandled.Theproblemwiththisisthatbutton1isn’tmeaningfulandwhen
youreturntothiscodelater,you’llbeconfusedbyhavingmethodsnamedbutton1_Click,
button2_Click,andsoon.Tofixthenamingproblem,youshouldnameyourcontrols
properlybeforedoinganythingelsewiththem.
Tobackoutofthis,gobacktotheEventstabofthePropertieswindow.Rememberto
selecttheButtonintheDesigner.ThetopleftofthePropertieswindowcontainstheIDof
thecontrol,whichyoushouldchangefrombutton1toameaningfulname.Forexample
ifthepurposeofthebuttonwastocreateaneworderforacustomer,youcouldnamethe
buttonNewOrderButton.ThendeletetheeventhandlerassignedtotheClickeventofthe
Button.Figure8-10showsthesechangesinthePropertieswindow.NowtheIDandevent
handleraremorereadable.
AftertheeventhandlerisdeletedandthecontrolhasanewID,double-clicktheClick
eventagain.VSwillcreateaneweventhandlerforyou,shownhere:
C#:
privatevoidbutton1_Click(objectsender,RoutedEventArgse)
{
}
privatevoidNewOrderButton_Click(objectsender,RoutedEventArgse)
{
}
232 MicrosoftVisualStudio2010:ABeginner’sGuide
VB:
ClassMainWindow
PrivateSubButton1_Click(
ByValsenderAsSystem.Object,
ByValeAsSystem.Windows.RoutedEventArgs)
EndSub
PrivateSubNewOrderButton_Click(
ByValsenderAsSystem.Object,
ByValeAsSystem.Windows.RoutedEventArgs)Handles
NewOrderButton.Click
EndSub
EndClass
Chapter8: BuildingDesktopApplicationswithWPF 233
Thepreviouscodeshowsboththeoldbutton1_Click(Button1_ClickinVB)event
handlerandthenewNewOrderButton_Clickeventhandler.Youmightwonderwhythe
button1_Clickeventhandlerwasn’tdeletedwhenyoudeleteditfromtheClickeventin
thePropertieswindow,butthere’sagoodreasonforthis.Whatifyouhadalreadywritten
codeintheeventhandler?VSleanstowardthesafesideanddoesnotdeleteyourcode.
Usingtheprevioussteps,youhavebotheventhandlerssittingside-by-side,whichmeans
thatyoucaneasilycopyyourcodefrombutton1_ClickintoNewOrderButton_Clickand
thendeletethebutton1_Clickeventhandler.Sofar,wehaven’twrittenanycodeforthe
eventhandler,whichyou’lllearnaboutinthenextsection.
TIP
The project’s Add | New Item context menu includes a Window entry, which can save a
couple of clicks when creating a new window.
AftertheDesignerloads,youcanquicklyopenthecode-behindbypressingF7.Inthe
code-behind,you’llseethefollowingcode:
C#:
publicpartialclassNewOrder:Window
{
publicNewOrder()
{
InitializeComponent();
}
}
VB:
PublicClassNewOrder
EndClass
234 MicrosoftVisualStudio2010:ABeginner’sGuide
NoticethattheclassinthiscodeisnamedNewOrder,illustratingthatawindowisjust
anotherclass.Asyouknow,youcaninstantiateclassesandcalltheirmethods,whichis
thetechniqueyou’llusetoopenthiswindowfromtheNewOrder_Clickeventhandlerin
thecode-behindoftheMainWindowwindow.
Inpractice,you’llpopulatetheNewOrderwindowwithwhatevercontrolsyouneed
toimplementaneworder.Youwouldpopulatethewindowbydragginganddropping
controls,justliketheButtoninthisexample.However,we’llskipthattaskfornow
becausethecurrentfocusisonaddingcodetotheNewOrderButton_Clickeventhandler
sothatyoucanlearnhowtocodeaneventhandlerandopenanotherwindow.Gobackto
theNewOrderButton_ClickeventhandlerinMainWindow.xaml.csandaddthefollowing
code:
C#:
privatevoidNewOrderButton_Click(objectsender,RoutedEventArgse)
{
NewOrdernewOrd=newNewOrder();
newOrd.Show();
}
VB:
PrivateSubNewOrderButton_Click(
ByValsenderAsSystem.Object,
ByValeAsSystem.Windows.RoutedEventArgs)
HandlesNewOrderButton.Click
DimnewOrdAsNewNewOrder
newOrd.Show()
EndSub
SinceNewOrderisaclass,youcaninstantiateitasshownintheprecedingcode
example.Toopenthewindow,calltheShowmethod.
NowyouhaveaWPFprogramthathandleseventsandopensnewwindows.PressF5
toruntheprogram.ClickNewOrderandobservethattheNewOrderwindowappears.
TheNewOrderwindowisn’tveryusefulbecauseitlackscontrolsanddatamanagement.
Thenextsectionshowsyouhowtopopulatewindowcontrolswithdata.
followingsectionsshowyouhowtoperformcreate,read,update,anddelete(CRUD)
operationsviaWPF.You’llfirstseehowtoinsertdata,usingVStoolstoconstructadata
entryscreen.Thenyou’lllearnhowtoread,modify,anddeletedatathroughaDataGrid.
We’llstartwithsinglevaluebinding.Tomaketheexamplesmoreinteresting,Iadded
extrafieldstothetables.YoucanreviewChapter7tolearnhowtoaddfieldstoadatabase
andcreateaLINQtoSQLentitymodel.
● OrderID,int,primarykey,auto-increment
● CustomerID,int
● OrderDate,datetime
● Location,varchar(50)
● Amount,money
ThenupdatetheCustomertablewiththefollowingfields:
● CustomerID,int,primarykey,auto-increment
● Name,nvarchar(50)
● Age,int
● Birthday,datetime
● Income,money
Withthedatabaseupdated,youcanaddaLINQtoSQLentitymodeltotheproject,
usingthesametechniquesdescribedinChapter7.
Toaddthedatasourceforbinding,opentheNewOrderwindowintheDesigner,and
selecttheData|AddNewDataSourcemenu,whichopenstheChooseADataSource
Typewindow,showninFigure8-11.
Therearedifferentwaystoconnecttoadatasource,includingdirectlytothedatabase,
viaaWebservice,viaanobject,orthroughSharePoint.Thisbookshowsyouhowtouse
LINQtoSQL,whichisconnectedbyselectingObjectandclickingNext,whichshowsthe
SelectTheDataObjectswindowinFigure8-12.
236 MicrosoftVisualStudio2010:ABeginner’sGuide
OntheSelectTheDataObjectswindow,checktheboxnexttoeachobjectyouwant
tobindinyourapplication.TheexampleinthischapterusesCustomerandOrderobjects,
whichyoucanseecheckedinFigure8-12.ClickingFinishwillconfigurethedatasource
foruseintheapplication.YoucanviewdatasourcesbyselectingData|ShowData
Sources,showninFigure8-13.
TheDataSourceswindowallowsyoutocreatecontrolsonaformthatarebound
toeachfieldofadatasource.IntheDataSourceswindowinFigure8-13,youcansee
thatbothCustomerandObjectarelistedwiththeirfields.Whatisalsoevidentisthe
iconsassociatedwitheachfield.Theiconsdescribewhattypeofcontrolshouldbe
associatedwitheachdatafield.Forexample,NameonCustomerisaTextBoxbecauseitis
nvarchar(50),butBirthdayisacalendarbecauseitisadatetime.Ifyoudon’tlikeadefault
controltypeforafield,youcanchangeitbyselectingthefieldandchoosinganother
controltypefromthedrop-downlist,asshowninFigure8-14.
Chapter8: BuildingDesktopApplicationswithWPF 237
InFigure8-14,theCustomerIDisbeingchangedtoaComboBoxbecauseitmakes
moresensetogivetheusertheoptionofselectingacustomerfromalistforaneworder,
ratherthantypinginanIDnumber.Also,theobjectdefaultstoaGridcontrol,butinthis
firstexample,weonlywanttoaddaneworder,meaningthatthecontroltypeshouldbe
changedtoDetail.Tocreateaneworderformwithcontrolsboundtoorderdata,selectthe
OrderobjectintheDataSourceswindowanddraganddroptheorderontotheDesigner
oftheNewOrderwindow.Figure8-15showsthisnewwindow.
Figure8-15showshowVSaddedaGridlayoutwithtwocolumnsandarowforeach
fieldintheOrdertable.Asexplained,theCustomerIDisaComboBoxandtheOrderDate
isacalendar.VSwassmartenoughtoputspacesbetweenthewordsinthelabels,too.
VSdidn’tputtheSavebuttononthescreen,whichissomethingyouwouldneedtodo
tosavethedata.InadditiontoaddingcontrolstotheDesigner,VSaddedthefollowing
CollectionViewSourcecontroltotheNewOrderwindow’sXAML:
<Window.Resources>
<CollectionViewSourcex:Key="orderViewSource"
d:DesignSource="{d:DesignInstancemy:Order,CreateList=True}"/>
</Window.Resources>
Chapter8: BuildingDesktopApplicationswithWPF 239
Thisisanotherreasonit’simportanttobeabletoreadtheXAMLforawindow,so
youcanseehowobjectslikethisareaddedandconfigurethemifyouneedto.Inour
case,weneedtoknowthenameoftheCollectionViewSource,whichisorderViewSource.
WeneedtoaddanOrderobjecttotheCollectionViewSourcesothatthecontrolsthatare
boundtoithaveaplacetosavedatathattheuserenters.PressF7toseethecodethatVS
addedtotheWindowLoadedeventhandler,asfollows:
C#:
privatevoidWindow_Loaded(objectsender,RoutedEventArgse)
{
System.Windows.Data.CollectionViewSource
orderViewSource=
((System.Windows.Data.CollectionViewSource)
(this.FindResource("orderViewSource")));
//Loaddatabysettingthe
//CollectionViewSource.Sourceproperty:
//orderViewSource.Source=[genericdatasource]
}
240 MicrosoftVisualStudio2010:ABeginner’sGuide
VB:
PrivateSubWindow_Loaded(
ByValsenderAsSystem.Object,
ByValeAsSystem.Windows.RoutedEventArgs)HandlesMyBase.Loaded
DimOrderViewSourceAsSystem.Windows.Data.CollectionViewSource
=CType(Me.FindResource("OrderViewSource"),
System.Windows.Data.CollectionViewSource)
'LoaddatabysettingtheCollectionViewSource.Sourceproperty:
'OrderViewSource.Source=[genericdatasource]
EndSub
TheprecedingskeletoncodegetsareferencetoOrderViewSource,butthat’sall.The
commentedportionofthecodesuggestshowyoumightpopulatethatcontrol.However,
wearen’tinterestedinpopulatingOrderViewSourcewithdatabecausethepurposeof
thisscreenistoinsertanewrecord.Instead,theproperapproachistobindanempty
object.Later,you’llseehowtopullthedatafromthatobjectaftertheuserfillsinthe
formandclicksontheSavebutton.InadditiontoassigningablankOrderobjectto
OrderViewSource,weneedtopopulatetheComboBoxthatholdsthelistofcustomers
andtheirIDs.ThefollowingcodeisarevisiontotheWindow_Loadedeventhandler
thatassignsablankOrderobjecttotheOrderViewSourceandbindscustomerstothe
ComboBoxholdingcustomers:
C#:
privatevoidWindow_Loaded(objectsender,RoutedEventArgse)
{
varorderViewSource=
FindResource("orderViewSource")asCollectionViewSource;
orderViewSource.Source=
newList<Order>
{
newOrder
{
OrderDate=DateTime.Now
}
};
customerIDComboBox.ItemsSource=
fromcustinnewMyShopDataContext().Customers
selectcust;
}
Chapter8: BuildingDesktopApplicationswithWPF 241
VB:
PrivateSubWindow_Loaded(
ByValsenderAsSystem.Object,
ByValeAsSystem.Windows.RoutedEventArgs)HandlesMyBase.Loaded
DimOrderViewSourceAsCollectionViewSource=
CType(FindResource("OrderViewSource"),CollectionViewSource)
OrderViewSource.Source=
NewList(OfOrder)From
{
NewOrderWith
{
.OrderDate=DateTime.Now
}
}
CustomerIDComboBox.ItemsSource=
FromcustInNewMyShopDataContext().Customers
EndSub
Thepreviousre-writeofWindow_Loadedaccomplishestwothings:assigninganorder
toorderViewSourceandpopulatingcustomerIDComboBoxwithcustomers.TheOrder
objectassignedtotheSourcepropertyoforderViewSourceisempty,exceptassigning
today’sdatetoOrderDate,demonstratinghowyoucansetdefaultvalues.Whentheuser
fillsouttheformonthepage,WPFwillpopulatethisOrderwithdatabecauseitisdata
bound,throughorderViewSource,tothecontrolsonthescreen.Thissectionshowedyou
howthedataisassignedtothecontrols,butsomecontrolsrequireevenmoreattentionto
ensuretheydisplaythedatacorrectly.Thenextsectionexpandsuponwhatyoumustdoto
gettheComboBoxtowork.
Configuring a ComboBox
AcoupleoftheparticularlymorecomplexcontrolstoconfigureareComboBoxand
ListBox.Thereasonisthattheyhaveafewdifferentpropertiesthatmustbesettoensure
thatwhateverisselectedcanbereadandcorrectlyreferencedbacktotheoriginaldata
source.Thissectiondoesn’ttrytoteachyouaboutWPFbindingbecausethereareentire
bookswithmultiplechaptersrelatedtothesubject.Instead,you’lllearnanessentialskill
forhelpingyoufigureouthowtosettherightpropertiesonaComboBoxcontrol.Inso
doing,you’llgetabetterfeelforthefeaturesofVSthathelpyouperformthetaskof
settingupcontrols.
242 MicrosoftVisualStudio2010:ABeginner’sGuide
ThepreviousexampleassignstheresultsofaLINQqueryforCustomerobjectsto
thecustomerIDComboBox,butthisisonlythefirststeptogettingthecomboboxtowork
properly;youmustspecifywhichpropertyofCustomermustdisplay,whichpropertyof
CustomermapstoOrder,andwhichpropertyofOrdertobindtheselecteditemto.Todo
thisbinding,opentheNewOrder.xamlfileintheDesigner,selectthecombobox,andset
thepropertiesasspecifiedinTable8-2.
ThefollowingXAMLshowstheresultsofthesettingsyoushouldmakeinthe
Propertieswindow,basedonTable8-2:
<ComboBoxDisplayMemberPath="Name"
SelectedValue="{BindingPath=CustomerID}"
SelectedValuePath="CustomerID"
Grid.Column="1"Grid.Row="1"
Height="23"HorizontalAlignment="Left"
Margin="3"Name="customerIDComboBox"
VerticalAlignment="Center"Width="120">
</ComboBox>
DisplayMemberPathandSelectedValuePatharenamesofthepropertiesfromthe
CustomerobjectsboundtotheComboBox.However,theSelectedValuesyntaxusesa
bindingexpression,wherePathidentifiesthepropertyoftheOrderthatwillbeassigned
towithSelectedValuePath.ThebindingforSelectedValueisbasedontheOrderobject
Property Explanation
ItemsSource We set this through code in the Window_Loaded event. It holds the collection
of objects that will appear in the combo box. You need two properties, one to
display and one for the key of the object being displayed. The key will be used
to map the object back to the database or associate the object in a relationship
with another object. In the case of the Customer list, the properties of interest are
Name for display and CustomerID for key. Since we are creating a new Order,
the CustomerID for the Name selected in the combo box will be assigned to the
CustomerID field of the Order. That way, when the Order is saved, its database
record will have the CustomerID for the customer the user selected.
DisplayMemberPath This is the Name property from each Customer object bound to the combo box.
SelectedValuePath As explained for ItemsSource, you need to associate the selected Customer with
the Order being created. SelectedValuePath is the name of the Customer object’s
key, which is CustomerID in our example.
SelectedValue When saving the Order, you must have the key associated with the selected
customer. The SelectedValue is a binding to the property of the Order that will
be set with the key from the selected Customer.
thatwasassignedtotheSourcepropertyoftheorderViewSourceinWindow_Loaded.
Comingfullcircle,theorderViewSourceiswhatthedefaultbindingofthecontaining
Gridlayoutisbasedon;itwassetwhendragginganddroppingtheOrderdatasource
ontotheDesignsurface.
Nowyouhaveaninputformthatdisplaysdata,allowingtheusertoenternew
orderinformation.Aftertheuserfillsintheform,youneedtosavethedata,whichis
discussednext.
VB:
PrivateSubSaveButton_Click(
ByValsenderAsSystem.Object,
ByValeAsSystem.Windows.RoutedEventArgs)
HandlesSaveButton.Click
DimOrderViewSourceAsCollectionViewSource=
CType(FindResource("OrderViewSource"),CollectionViewSource)
244 MicrosoftVisualStudio2010:ABeginner’sGuide
DimordListAsList(OfOrder)
ordList=CType(OrderViewSource.Source,List(OfOrder))
DimordAsOrder
ord=ordList.FirstOrDefault()
DimctxAsNewMyShopDataContext
ctx.Orders.InsertOnSubmit(ord)
ctx.SubmitChanges()
MessageBox.Show("OrderSaved!")
EndSub
BeforetheSaveButton_Clickeventhandlerends,itshowsamessageboxtotheuser
withastatusmessage,OrderSaved.TheMessageBoxclasshasseveraloverloadsofthe
Showmethodthatallowsyoutospecifybuttons,icons,andmore.
Sofar,you’velearnedhowtocreateaninputformforaddinganewrecordtothe
database.Thenextsectionwillbuilduponthisbyshowingyouhowtoview,modify,and
deleterecordswiththeDataGrid.
C#:
privateMyShopDataContextm_ctx=newMyShopDataContext();
privatevoidWindow_Loaded(objectsender,RoutedEventArgse)
{
CollectionViewSourceorderViewSource=
FindResource("orderViewSource")asCollectionViewSource;
orderViewSource.Source=
fromordinm_ctx.Orders
selectord;
}
VB:
Dimm_ctxAsNewMyShopDataContext
PrivateSubWindow_Loaded(
ByValsenderAsSystem.Object,
ByValeAsSystem.Windows.RoutedEventArgs)
HandlesMyBase.Loaded
246 MicrosoftVisualStudio2010:ABeginner’sGuide
DimOrderViewSourceAsCollectionViewSource=
CType(FindResource("OrderViewSource"),CollectionViewSource)
OrderViewSource.Source=
FromordInm_ctx.Orders
Selectord
EndSub
ThiscodeloadsordersintotheGrid.NoticethattheMyShopDataContext,m_ctx,isa
fieldoutsideoftheWindow_Loadedmethodhandler.Itisraisedtofieldlevelsothatthe
sameinstancecanbeusedinmultiplemethods.AsyoumaynoticefromFigure8-16,there
isalsoanUpdatebuttonontheform.Double-clickingtheUpdatebuttonproducedthe
followingClickeventhandlerthatsaveschanges,suchasupdatesanddeletes,totheGrid:
C#:
privatevoidUpdateButton_Click(objectsender,RoutedEventArgse)
{
m_ctx.SubmitChanges();
MessageBox.Show("UpdatesandDeletesSaved!");
}
VB:
PrivateSubUpdateButton_Click(
ByValsenderAsSystem.Object,
ByValeAsSystem.Windows.RoutedEventArgs)
HandlesUpdateButton.Click
m_ctx.SubmitChanges()
MessageBox.Show("UpdatesandDeletesSaved!")
EndSub
Whenyouruntheprogram,youcanaddnewrows,modifythecellsofexistingrows,
ordeletearowbyselectingtherowandpressingDELETEonthekeyboard.Aftermaking
changestotheGrid,clickUpdate,whichwillcallthepreviousUpdateButton_Clickevent
handler.
Tounderstandhowthisworks,rememberthattheWindow_Loadedeventhandler
assignedacollectionofOrderobjectstotheCollectionViewSource,orderViewSource,
whichisdataboundtotheGrid.EachrowoftheGridisboundtoaninstanceofanOrder
object.EachOrderobjectispartoftheLINQtoSQLMyShopDataContext.Sinceweare
Chapter8: BuildingDesktopApplicationswithWPF 247
usingm_ctx,whichisafield,boththeWindow_LoadedmethodandtheUpdateButton_
Clickmethodareusingthesameobjectinstance.WhenmakingchangesintheGrid,
thosechangesaresavedintheOrderobjectsforthechangedrows.TheOrderobjects
notifyMyShopDataContextthattheyhavechanged,whichisaserviceofLINQtoSQL.
TheUpdateButton_Clickmethodusesm_ctx,whichistheMyShopDataContextthat
knowsaboutthechangestotheOrderobjects.CallingSubmitChangesonm_ctxsavesall
changestothedatabase.
Youmightneedtoreadtheprecedingparagraphmorethanonetimetounderstand
howthisisworking.Ifit’sstillfuzzy,itmightbehelpfultoreviewthelanguagechapters
earlierinthisbooktounderstandhowobjectsareinstantiatedandused,andreview
Chapter7toensureyouunderstandthedatamanipulationpicture.
Summary
WhilethereismuchmoretolearnaboutWPF,thisisabeginner’sguideandintendedto
giveyoutheessentialssothatyoucanbeginmovingintherightdirection.Youshould
nowbeabletocreateanewWPFproject.Youlearnedaboutlayoutcontrolsandhowthey
allowyoutomanagehowcontrolsappearonyourform.Asectionexplainsthewindows
involvedinworkingwithcontrols.Whiletherearemanycontrolsyoucanusethatship
withbothWPFandmanythird-partyproducts,rememberthattheconceptsarerelatively
thesameforusingthecontrols:draganddrop,andconfigureproperties.Mostapplications
workwithdata,sothischapterbuildsuponwhatyouknowaboutLINQtoSQLand
showsyouhowtoapplythisdatamanagementknowledgetocreateuserinterfacesthat
userscanworkwithtomanagetheirdata.
Thischapterintroducesyoutoworkingwithdesktopapplications,whicharestillvery
necessaryandpopular.However,alotoftoday’sapplicationsarewrittenfortheInternet.
ThenextchaptershowsyouhowtobuildWebapplicationswithASP.NET.
This page intentionally left blank
Chapter
Creating Web
9
Applications with
ASP.NET MVC
249
250 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● LearnWhatMVCMeans
● CreateModels
● CreateControllers
● CreateViews
● WorkwithDatainASP.NETMVC
A SP.NETisa.NETtechnologyforbuildingWebapplications.VSprovidessupport
forbuildingaWebapplicationthroughwindowssuchastheToolbox,Designer,and
Propertieswindows,aswellastheSolutionExplorer.Thischaptershowsyouhowtouse
ASP.NETMVC.MVCisanacronymforModelViewController,whichisawell-known
designpatternforbuildingapplications.You’lllearnabouthowMVCworksandhowitis
implementedinASP.NETMVC.Let’sstartbyhelpingyouunderstandwhatMVCis.
MVCObject Purpose
Model The Model is made up of business objects and data.
View Each MVC application typically has a user interface that displays information to a
user and allows the user to input data. The data that the View displays is read from
a Model, and the data that the user adds to the View is assigned to the Model.
Controller A Controller orchestrates the activities of an application. When a user makes a
request for your application, ASP.NET MVC invokes a Controller. The Controller will
communicate with the Model and View to ensure the program operates correctly.
Request
Controller
View Model
View,andtheController,includingrelationships.Therearevariationsoftherelationship
betweenModel,View,andController,soratherthanatheoreticallycorrectdepictionofall
scenarios,Figure9-1isasimplificationthatshouldhelpyougetstarted.
InFigure9-1,youcanseethattheControllerreferencesboththeViewandtheModel.
ThismakessensewhenyouconsiderthattheControllerismanagingtheoperationofthe
application.TheControllerexecutesinresponsetoauserrequest.SincetheController
isalsoresponsibleforcoordinatingactivitybetweentheModelandtheView,youcan
seetherelationshipinFigure9-1wheretheControllerreferencestheModel.TheView
referencestheModelbecausetheViewmustbinddatatotheuserinterfaceandneedsto
knowwhatdataisavailable.TheModeldoesnotreferencetheViewortheController.The
Modelisanobjectthatholdsdataandanyothermembersthathelpmanagethatdata,such
asmethodsforperformingvalidation.
AtypicalsequenceofoperationsforanASP.NETMVCoperationstartswitharequest
toaController.TheControllerwillperformtheactionsrequested,workingwiththeModel.
TheControllerwillthengivetheModeltoaViewandruntheView.TheViewwilldisplay
Modeldataandinteractwiththeuserforanyscreenoperations.Basedonuserinteraction
withtheView,morerequestswillbemadetoaControllertorepeatthisprocess.Therest
ofthischaptershowsyouhowtowritethecodetomakethisprocesswork,startingwith
creatinganewASP.NETMVCproject.
youhavetheoptiontochooseYesorNo.ChoosingYeswilladdaunittestingprojectto
thesolution.Youcanchooseeitheroption,whichwon’tmatterrightnowbecausewe’llnot
becoveringthistopichere,butitisdefinitelyworthexploringonyourown.Figure9-2
showsthenewprojectinSolutionExplorer.
VScreatedseveralfolderswithworkingcode:
● TheModel,View,andControllerfoldersholdcodefortheMVCModels,Views,and
Controllers,respectively.
● PreviouschaptersalreadyexplainedthepurposeofthePropertiesandReferencesfolders.
● TheApp_Datafolderisdesignedtoallowyoutoshipalocaldatabasewithyourapplication
andisidealforsmallprogramswhereyoucanusethefreeSQLExpressdatabase.See
theaccompanyingnotetolearnhowtoaddadatabaseintheApp_Datafolder.
● TheContentfolderiswhereyouaddanyCascadingStyleSheets(CSS)files.CSSisa
standardizedlanguagefordefininglayoutandappearanceofaWebsite.
● TheScriptsfolderholdsJavaScriptfiles,whichincludethejQueryandASP.NET
AJAXclientlibraries.JavaScripthelpsmakeViewsmoreinteractiveandcanbe
effectiveinprovidingapleasinguserexperience.
● TheGlobal.asaxfileholdscodethatrunsatdifferentperiodsduringtheapplication
lifecycle;we’llinvestigatethisfilewhenlookingatroutinglaterinthischapter.
● Theweb.configfileholdsconfigurationinformation,suchasdatabaseconnection
stringsandmoreitemsthatyoudon’twanttohard-codeintotheapplication.
NOTE
If you want to ship a local database with your application, you can right-click the App_
Data folder for your project, select Add | New Item, navigate to Data, and select SQL
Server Database. This will add a blank database *.mdf file under the App_Data folder.
You can work with this database through Server Explorer, using techniques learned in
Chapter 7, to add tables and other objects. Remember that the server you deploy to
must have SQL Server Express installed or your database operations won’t work.
ThecodegeneratedbytheNewProjectWizardwillrun,andpressingF5toexecutethe
applicationwillshowyouascreensimilartoFigure9-3.ClickOKwhenyouseeascreen
thatasksifyouwanttoprogramtorunindebugmode.Thiswillmodifytheweb.config
filetoallowdebugging,whichiswhatyouwantwhiledevelopingapplications.
TheskeletoncodeproducedbyVSgivesyousomeworkingexamplesthatyoucan
buildonandmoveforward.OneitemthatVSdoesn’tproduceistheModel,whichis
discussednext.
Building Controllers
RequestscomedirectlytoaController,whichwediscussedearlier.AsshowninFigure9-2,
theMVCprojecthasaControllersfolder.ControllerclassesnormallyresideintheControllers
folder.Figure9-2showstwofiles,AccountController.csandHomeController.cs,inthe
Controllersfolder.Listing9-1showsthecontentsoftheHomeController.csfile.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.Mvc;
namespaceMyShopCS.Controllers
{
[HandleError]
publicclassHomeController:Controller
{
publicActionResultIndex()
{
ViewData["Message"]="WelcometoASP.NETMVC!";
Chapter9: CreatingWebApplicationswithASP.NETMVC 255
returnView();
}
publicActionResultAbout()
{
returnView();
}
}
}
VB:
<HandleError()>_
PublicClassHomeController
InheritsSystem.Web.Mvc.Controller
FunctionIndex()AsActionResult
ViewData("Message")="WelcometoASP.NETMVC!"
ReturnView()
EndFunction
FunctionAbout()AsActionResult
ReturnView()
EndFunction
EndClass
Listing9-1demonstrateshowcloselyASP.NETMVCistiedtoconventions.Notice
thattheclassnameisHomeController.AppendingControllertoaclassnameisa
conventionthatASP.NETMVCusestoidentifywhichclassesarecontrollers.Also,the
methodsintheclassarereferredtoasActionsinASP.NETMVC.UsingtheControllers
folderforaController,appendingtheclassnamewithController,andavailableactions
areallconventionsthatyoumustfollow.ThefollowingURL,abrowseraddress,
demonstrateshowtheseconventionssupportroutingtofindaControllerandinvokethe
Aboutaction.YoucanseethisURLifyouruntheapplicationandclicktheAbouttab:
http://localhost:1042/Home/About
Thehttp://localhost:1042partoftheURLisaWebserverthatisbuiltintoVSandrunsthe
WebapplicationwithoutneedingaWebserversuchasInternetInformationServer(IIS).
Thenumber1042isarandomportnumbergeneratedbytheWebserver,andyourport
numberislikelytobedifferent.
256 MicrosoftVisualStudio2010:ABeginner’sGuide
TIP
You can change your VS Web server’s port number. If you open your project’s property
page by right-mouse clicking on the project in Solution Explorer and select Properties,
then select the Web tab on the left, under Servers, you can specify a specific port or
make other Web server choices.
ForASP.NETMVC,theimportantpartoftheURLis/Home/About.Homeisthe
nameoftheController,andASP.NETMVCappendsControllertotheURLname,looking
fortheHomeControllerclass,showninListing9-1,physicallylocatedintheController
folder,whichiswhyit’simportanttoensureyoucreatefilesintheproperlocations.About
isanaction,whichcorrespondstotheAboutmethodshowninListing9-1.Similartothe
Aboutmethod,theIndexactionisrunthroughthefollowingURL:
http://localhost:1042/Home/Index
Inalatersectionofthischapter,you’lllearnhowASP.NETMVCperformsrouting,which
mapsURLstoControllers.
BoththeIndexandAboutactionsinListing9-1invokeamethodnamedView.Thisis
aconventionforinvokingaViewwiththesamenameastheactionmethod.Forexample,
callingViewintheIndexactionwillshowaViewnamedIndex,andthecalltoViewinthe
AboutmethodwillshowaViewnamedAbout.
OnemoreitemtopointoutishowtheIndexactionassignsastringtoacollection
calledViewData.TheViewDatacollectionisonewayforaControllertopassModeldata
toaView.I’llcovermoreonControllers,includinghowtocreateyourown,inalaterpart
ofthischapter,butnow,let’sdoaquickreviewofViewssothatyoucanseewhathappens
whentheyareinvokedbytheController.
Displaying Views
AViewiswhatdisplaysinthebrowserandallowsinteractionwiththeuser.TheViewcan
displayanyinformationthataControllerpassestoit.Forexample,noticethattheIndex
actioninListing9-1assignsastring“WelcometoASP.NETMVC!”withthe“Message”
keyintheViewDatacollection.
<%@PageLanguage="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage"%>
<asp:ContentID="indexTitle"
ContentPlaceHolderID="TitleContent"
runat="server">
HomePage
</asp:Content>
<asp:ContentID="indexContent"
ContentPlaceHolderID="MainContent"
runat="server">
<h2><%=Html.Encode(ViewData["Message"])%></h2>
<p>
TolearnmoreaboutASP.NETMVCvisit
<ahref="http://asp.net/mvc"
title="ASP.NETMVCWebsite">
http://asp.net/mvc
</a>.
</p>
</asp:Content>
AquickoverviewofListing9-2showsthatthereisaPagedirectivewithacoupleof
Contentcontainers.ThePagedirectivespecifiesaMasterPageandInheritsattributes.
AMasterPageisaseparatefilethatholdscommonHTMLthatcanbeshownonallpages
ofasite.You’llseehowtheMasterPageworkssoon,butlet’sstayfocusedonthecurrent
fileinListing9-2untilthen.ASP.NETMVCwillcompilethisHTMLintocodebehindthe
scenes,andthegeneratedcodewillderivefromtheclassdefinedbytheInheritsattribute.
ThefirstContentcontainercanholdmetadatathatgoesintoanHTMLheader.The
secondContentcontainerhastheinformationthatwilldisplayonthescreen.Notice
theHtml.Encode(ViewData["Message"])insideofbindingtags<%=and%>.Anytime
youaddcodeorneedtoaccessViewDatathatwaspassedbytheController,youwill
usethebindingtags.EncodeisoneofseveralhelpermethodsoftheHtmlclass,more
ofwhichyou’llseesoon.ThepurposeofEncodeistotranslateHTMLtagsintotheir
encodedrepresentationsforsecuritypurposes,ensuringthatyoudon’tshowanyharmful
JavaScript,orothermarkupthatcouldpossiblyexecute,totheuser.ViewData["Message"]
shouldbefamiliar,asitwassetintheIndexactioninListing9-2butisnowbeingread
anddisplayedonthescreenbythisView.
258 MicrosoftVisualStudio2010:ABeginner’sGuide
Listing9-3 A MasterPage
<%@MasterLanguage="C#"
Inherits="System.Web.Mvc.ViewMasterPage"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
Chapter9: CreatingWebApplicationswithASP.NETMVC 259
<title>
<asp:ContentPlaceHolderID="TitleContent"
runat="server"/>
</title>
<linkhref="../../Content/Site.css"
rel="stylesheet"type="text/css"/>
</head>
<body>
<divclass="page">
<divid="header">
<divid="title">
<h1>MyMVCApplication</h1>
</div>
<divid="logindisplay">
<%Html.RenderPartial("LogOnUserControl");%>
</div>
<divid="menucontainer">
<ulid="menu">
<li>
<%=Html.ActionLink("Home","Index","Home")%>
</li>
<li>
<%=Html.ActionLink("About","About","Home")%>
</li>
</ul>
</div>
</div>
<divid="main">
<asp:ContentPlaceHolderID="MainContent"runat="server"/>
<divid="footer">
</div>
</div>
</div>
</body>
</html>
260 MicrosoftVisualStudio2010:ABeginner’sGuide
MovingfromthetopofListing9-3down,youcanseetheMasterPagedirectiveatthetop
ofthepage,whichstatesthatthisisaMasterPageandASP.NETMVCwillhandlethepage
appropriately.TheDTDisatagthatspecifieswhatWebstandardsthispagesupports,which
isreadbybrowserstohelpthemdeterminethebestwaytodisplaythepage.
TherestofthepageisframedinsideofHTMLtagsandASP.NETMVCmarkup.The
htmltagstatesthatthisisanHTMLdocument.HTMLdocumentshavetwoparts,ahead
andabody,wheretheheadisformetadatadescribingthepageandthebodycontains
displaycontent.
InHTML,adivtagblocksoffachunkofHTMLandisusefulforlayoutandorganization
ofthepage.TheHxtags,wherexisanumberbetween1and6,describeheaders,whereh1is
thelargestandh6isthesmallest.
TheContentPlaceHoldercontrolsareinstrumentaltothesuccessoftheMasterPage.If
youlookattheContenttagsinListing9-2,you’llseethattheyhaveaContentPlaceHolderID
thatmatchestheIDattributesoftheContentPlaceHoldercontrolsinListing9-3.Whatthis
meansisthatwhentheViewrenders,theMasterPagewilldisplayandASP.NETMVCwill
injecttheContentregionsofthecontentpagesintothematchingContentPlaceHoldersofthe
MasterPage.ASP.NETMVCknowswhichMasterPagetousebecausethePagedirective,as
showninListing9-2,specifiestheMasterPageattribute.
Ifyourecallfromthelastsection,Listing9-2hadabindingexpressionfortheHtml
Encodehelpermethod.TheMasterPageinListing9-3introducesacouplemoreHtml
helpermethods,RenderPartialandActionLink.
TheActionLinkmethodhasthreeparameters:id,controller,andaction.Whenthe
ActionLinkrendersinthebrowser,itwilltransformintoananchortag,a,withanid
specifiedinthefirstparameterofActionLink.Whentheuserclicksthelinkinthebrowser,
theapplicationwillnavigatetotheControllerinthethirdparameterofActionLinkand
invoketheactioninthesecondparameterofActionLink.So,iftheuserclickedthelink
producedbyActionLink("About","About","Home"),ASP.NETMVCwillinvoketheAbout
actionoftheHomeController.ThenextsectiondiscussesRenderPartialinmoredetail.
AgoodexampleofwhereaPartialViewisusefulisillustratedinthecodeproduced
bytheASP.NETMVCProjectWizard,whereitcreatedtheLogonUserControl.ascx.The
termsPartialViewandUserControlaresynonymous,wherethetermUserControlis
familiartodeveloperswhohaveworkedwithpreviousversionsofASP.NETWebForms.
PartialViewisconsistentwiththeASP.NETMVCperspectiveofViews,whereaPartial
ViewisnotanentireView,butachunkofViewcontentthatcanbereusedwithmultiple
Views.Itisn’tcoincidencethatthiscontrolisphysicallylocatedintheViewsShared
folder,consideringthatitcanbeusedonmultiplepages.Remember,ifASP.NETMVC
can’tfindafileinaViewfoldernamedafteraController,itwilllookintheSharedfolder.
Listing9-4showsthecontentsofLogonUserControl.ascx.
<%@ControlLanguage="C#"
Inherits="System.Web.Mvc.ViewUserControl"%>
<%
if(Request.IsAuthenticated){
%>
Welcome<b><%=Html.Encode(Page.User.Identity.Name)%></b>!
[<%=Html.ActionLink("LogOff","LogOff","Account")%>]
<%
}
else{
%>
[<%=Html.ActionLink("LogOn","LogOn","Account")%>]
<%
}
%>
TheControldirectiveatthetopofListing9-4indicatesthatthisisaPartialView.
Withinthecontrol,youcanseeanifstatement,wherethelanguagesyntaxissurrounded
by<%and%>bindingsymbols.Theadditionalsyntaxtoseparatecodefrommarkup
mighttakealittlegettingusedto,butitistypicalinanMVCapplicationtocontrolhow
markupisrendered.TheIsAuthenticatedpropertyoftheRequestobjecttellswhether
thecurrentuserisloggedin,andthelogicensurestheappropriatemessagedisplays.
TheActionLinkHtmlhelpermethodsgenerateactiontagswithaURLforactionsonthe
AccountController.We’vebarelytouchedonroutingandhowaURLmatchescontrollers
andactions,butthenextsectionexplainshowroutesworkingreaterdepth.
262 MicrosoftVisualStudio2010:ABeginner’sGuide
Managing Routing
ASP.NETMVChasaroutingsystemthatmatchesURLstocontrollerswithactionsand
theparameterspassedtothoseactions.WhenyoustartanewASP.NETMVCproject,
defaultroutingwillbeestablishedviaafilecalledGlobal.asax,whichiswheremany
eventsaffectingtheapplicationareplaced.WhenyourunanASP.NETMVCapplication,
itwilluseURLsoftheformhttp://domain/controller/action/param1/param2/…/paramN?
optionalArg=optionalVal.Here’sanexample:
http://localhost:1042/Home/About
Inthisexample,localhost:1042isthedomain,HomeistheController,andAboutisthe
action.WhenASP.NETMVCseesthisURL,itwillinstantiatetheHomeControllerclass
andcalltheAboutmethod.
TheGlobal.asaxfilehasanApplication_Starteventthatiscalledthefirsttimethe
applicationruns.Thisiswhereroutingissetupsothatitwillbeinplaceforallofthe
requestswhiletheapplicationisrunning.Listing9-5showsthedefaultroutingforanASP
.NETMVCproject.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.Mvc;
usingSystem.Web.Routing;
namespaceMyShopCS
{
//Note:ForinstructionsonenablingIIS6orIIS7classicmode,
//visithttp://go.microsoft.com/?LinkId=9394801
publicclassMvcApplication:System.Web.HttpApplication
{
publicstaticvoidRegisterRoutes(RouteCollectionroutes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",//Routename
"{controller}/{action}/{id}",//URLwithparameters
new{
Chapter9: CreatingWebApplicationswithASP.NETMVC 263
controller="Home",
action="Index",
id=""}//Parameterdefaults
);
}
protectedvoidApplication_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
}
VB:
'Note:ForinstructionsonenablingIIS6orIIS7classicmode,
'visithttp://go.microsoft.com/?LinkId=9394802
PublicClassMvcApplication
InheritsSystem.Web.HttpApplication
SharedSubRegisterRoutes(ByValroutesAsRouteCollection)
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
'MapRoutetakesthefollowingparameters,inorder:
'(1)Routename
'(2)URLwithparameters
'(3)Parameterdefaults
routes.MapRoute(_
"Default",_
"{controller}/{action}/{id}",_
NewWith
{
.controller="Home",.action="Index",.id=""
}
)
EndSub
SubApplication_Start()
AreaRegistration.RegisterAllAreas()
RegisterRoutes(RouteTable.Routes)
EndSub
EndClass
264 MicrosoftVisualStudio2010:ABeginner’sGuide
Listing9-5showsthattheApplication_Starteventinvokesamethodnamed
RegisterRoutes,passingtheRoutespropertyoftheRouteTableclass.TheRoutespropertyis
astaticRouteCollection,meaningthatthereisonlyonecopyfortheentireapplication,and
itwillholdmultipleroutes.Whentheapplicationstarts,thiscollectionwillbeemptyand
theRegisterRoutesmethodwillpopulatethecollectionwithroutesforthisapplication.
Routingworksbypatternmatching,whichyoucanseethroughthetwostatements
intheRegisterRoutesmethod:IgnoreRouteandMapRoute.IgnoreRouteisusefulfor
situationswhereyouwanttoletIISrequesttheexactURL.Inthiscase,itisanyfilewith
the*.axdextension,regardlessofparameters.
TheMapRoutemethodshowsacommonpatternformatchingURLstocontrollers,
actions,andparameters.Thefirstparameteristhenameoftheroute.Thesecond
parameterdescribesthepattern,whereeachpatternmatchisdefinedbetweencurlybraces.
BasedontheURL,http://localhost:1042/Home/About,thepattern,{controller}/{action}/
{id},matchesHometo{controller}andAboutto{action};thereisnomatchfor{id}.
Therefore,ASP.NETMVCwillappend“Controller”totheURLsegmentthatmatches
{controller},meaningthattheControllernametoinstantiateisHomeController.About
isthemethodinsideofHomeControllertoinvoke.SinceAboutdoesn’thaveparameters,
supplyingthe{id}isunnecessary.
ThethirdparameterforMapRoutespecifiesdefaultvalues,wherethekeymatchesthe
patternparameterandthevalueassignedtothekeyiswhatASP.NETMVCuseswhenit
doesn’tfindapatternmatchwiththeURL.Hereareacoupleofexamples:
● http://localhost:1042invokestheIndexmethodofHomeControllerbecausenoController
oractionmatchesandthedefaultsareHomefor{controller}andIndexfor{action}.
● http://localhost:1042/HomeinvokestheIndexmethodofHomeControllerbecauseno
actionwasspecifiedandthedefaultvaluefor{action}isIndex.
YoucancreateyourowncustomroutebyusingtheMapRoutemethodandspecifying
otherdefaultvaluesfortheparameters.
Creating a Repository
Acommonpatternforworkingwithdataistobuildarepositorythatisresponsibleforall
data-relatedoperations.Thisisanotherwaytopromoteseparationofconcernssothatyou
isolatelogicintospecificpartsofanapplication,resultingineasiercodetoworkwith.
Arepositoryisaclassthatperformscreate,read,update,anddelete(CRUD)operations
onaspecificdatatype.Listing9-6showsarepositoryforworkingwithcustomerobjects.
Youcancreatethisclassbyright-clickingtheModelsfolderandselectingAdd|Class,
andnametheclassCustomerRepository.Thecodealsoassumesthatyou’vecreateda
LINQtoSQL*.dbml,namedMyShop,withaCustomerentityfortheCustomerstablein
MyShop,whichisthedatabasecreatedinChapter7.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
namespaceMyShopCS.Models
{
publicclassCustomerRepository
{
privateMyShopDataContextm_ctx
=newMyShopDataContext();
publicintInsertCustomer(Customercust)
{
m_ctx.Customers.InsertOnSubmit(cust);
m_ctx.SubmitChanges();
returncust.CustomerID;
}
publicvoidUpdateCustomer(Customercust)
{
varcurrentCust=
(fromcurrCustinm_ctx.Customers
wherecurrCust.CustomerID==cust.CustomerID
selectcurrCust)
.SingleOrDefault();
if(currentCust!=null)
266 MicrosoftVisualStudio2010:ABeginner’sGuide
{
currentCust.Age=cust.Age;
currentCust.Birthday=cust.Birthday;
currentCust.Income=cust.Income;
currentCust.Name=cust.Name;
}
m_ctx.SubmitChanges();
}
publicCustomerGetCustomer(intcustID)
{
return
(fromcustinm_ctx.Customers
wherecust.CustomerID==custID
selectcust)
.SingleOrDefault();
}
publicList<Customer>GetCustomers()
{
return
(fromcustinm_ctx.Customers
selectcust)
.ToList();
}
publicvoidDeleteCustomer(intcustID)
{
varcustomer=
(fromcustinm_ctx.Customers
wherecust.CustomerID==custID
selectcust)
.SingleOrDefault();
m_ctx.Customers.DeleteOnSubmit(customer);
m_ctx.SubmitChanges();
}
}
}
VB:
PublicClassCustomerRepository
Privatem_ctxAsNewMyShopDataContext
Chapter9: CreatingWebApplicationswithASP.NETMVC 267
PublicFunctionInsertCustomer(
ByValcustAsCustomer)AsInteger
m_ctx.Customers.InsertOnSubmit(cust)
m_ctx.SubmitChanges()
Returncust.CustomerID
EndFunction
PublicSubUpdateCustomer(ByValcustAsCustomer)
DimcurrentCust=
(FromcurrCustInm_ctx.Customers
WherecurrCust.CustomerID=cust.CustomerID
SelectcurrCust).SingleOrDefault()
IfNotcurrentCustIsNothingThen
WithcurrentCust
.Age=cust.Age
.Birthday=cust.Birthday
.Income=cust.Income
.Name=cust.Name
EndWith
m_ctx.SubmitChanges()
EndIf
EndSub
PublicFunctionGetCustomer(ByValcustIDAsInteger)AsCustomer
Dimcustomer=
(FromcustInm_ctx.Customers
Wherecust.CustomerID=custID
Selectcust).SingleOrDefault()
Returncustomer
EndFunction
PublicFunctionGetCustomers()AsList(OfCustomer)
Dimcustomers=
268 MicrosoftVisualStudio2010:ABeginner’sGuide
(FromcustInm_ctx.Customers
Selectcust).ToList()
Returncustomers
EndFunction
PublicSubDeleteCustomer(ByValcustIDAsInteger)
Dimcustomer=
(FromcustInm_ctx.Customers
Wherecust.CustomerID=custID
Selectcust).SingleOrDefault()
m_ctx.Customers.DeleteOnSubmit(customer)
m_ctx.SubmitChanges()
EndSub
EndClass
Youcanhavemoremethodsinarepositoryfordoingwhateverisrequiredwithdata
fortheapplication,buttheitemsinListing9-6aretypical.TheLINQtoSQLoperations
areconsistentwiththematerialcoveredinChapter7,sothere’snoneedtorepeatthesame
materialhere.ThepurposeoftherepositoryistogivetheControlleranobjecttowork
withforgettingdatawithoutfillingupControllermethodswithdataaccesslogic.Let’s
seehowtheControllerworkswiththisrepositorynext.
ThiswillcreateanewControllerwithseveralmethodsforworkingwithCustomer
data.Listing9-1alreadyshowedwhataControllerlookslike,andthisisnodifferent,
exceptthatitcontainsmoreactionmethods.Thefollowingsectionsexplainhowto
performvariousoperationsoncustomerdata.
C#:
publicActionResultIndex()
{
varcustomers=
newCustomerRepository()
.GetCustomers();
returnView(customers);
}
VB:
FunctionIndex()AsActionResult
DimcustRepAsNewCustomerRepository
DimcustomersAsList(OfCustomer)
customers=custRep.GetCustomers()
ReturnView(customers)
EndFunction
Listing9-7showshowtheIndexmethodusestheCustomerRepositorytogetthelist
ofcustomers.YouneedtopassthatlisttotheViewfordisplay.
TocreatetheView,right-clickanywhereintheIndexmethodandselectAddView,
whichwilldisplaytheAddViewwindow,showninFigure9-5.
ThenameoftheViewisIndex,correspondingtothenameoftheactionmethod
invokingtheView.NamingtheViewaftertheactionmethodisthedefaultbehavior,but
270 MicrosoftVisualStudio2010:ABeginner’sGuide
youcannametheViewanythingyouwant.IftheViewyouneedtodisplayisnamed
differentlythantheactionmethod,youcanusethefollowingViewmethodoverload:
View("SomeOtherViewName",customers);
WewanttouseastronglytypedView,meaningthatyouwillhaveIDEsupportfor
referencingthepropertiesofyourownobjectwhenworkingintheView.Theselected
objectisCustomer,whichisalreadydefinedasaLINQtoSQLentity,whichisthesame
typereturnedbythecalltotheGetCustomersmethodinCustomerRepository.
ThepurposeofthisViewistodisplayalistofcustomers,sowe’llselectListasView
content.ThiswillprepopulatetheViewwithatemplatefordisplayingcustomers.You’ll
beabletomodifythescreenasyoulike.Additionally,ifyouprefertowriteyourown
codetopopulatethescreen,youcanselecttheEmptyoptionforViewcontentandthen
codetheViewmanuallyyourself.SelectingListisaquickwaytogetstarted.
YoulearnedaboutMasterPagesearlierinthischapter,andyouhavetheoptionof
selectingaMasterPageofyourchoiceandspecifyingwhichContentPlaceHolderyour
codewillrenderin.
ClickAddtogeneratetheViewshowninListing9-8.
Chapter9: CreatingWebApplicationswithASP.NETMVC 271
<%@PageTitle=""Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc
.ViewPage<IEnumerable<MyShopCS.Models.Customer>>"%>
<asp:ContentID="Content1"
ContentPlaceHolderID="TitleContent"
runat="server">
Index
</asp:Content>
<asp:ContentID="Content2"
ContentPlaceHolderID="MainContent"
runat="server">
<h2>Index</h2>
<table>
<tr>
<th></th>
<th>
CustomerID
</th>
<th>
Name
</th>
<th>
Age
</th>
<th>
Birthday
</th>
<th>
Income
</th>
</tr>
<%foreach(variteminModel){%>
<tr>
<td>
<%=Html.ActionLink("Edit","Edit",
new{id=item.CustomerID})%>|
<%=Html.ActionLink("Details","Details",
new{id=item.CustomerID})%>
</td>
272 MicrosoftVisualStudio2010:ABeginner’sGuide
<td>
<%=Html.Encode(item.CustomerID)%>
</td>
<td>
<%=Html.Encode(item.Name)%>
</td>
<td>
<%=Html.Encode(item.Age)%>
</td>
<td>
<%=Html.Encode(String.Format("{0:g}",
item.Birthday))%>
</td>
<td>
<%=Html.Encode(String.Format("{0:F}",
item.Income))%>
</td>
</tr>
<%}%>
</table>
<p>
<%=Html.ActionLink("CreateNew","Create")%>
</p>
</asp:Content>
Listing9-8organizesthelistofCustomersinatable.Thetrtagsarerows,thare
headercells,andtdarecontentcells.Afterspecifyingtheheaderrow,theforeachloop
iteratesontheModeltorendereachcontentrow.IfyourecallfromListing9-7,the
IndexactionmethodcalledViewwithaList<Customer>(List(OfCustomer)inVB).
WhencreatingtheView,wespecifiedtheobjecttypeasCustomer,whichmeansthatthe
referencetoModelintheforeachstatementistoList<Customer>anditemcontainsa
Customerobject.
Foreachcellbeingrendered,itemisthecurrentCustomerandthepropertyforthat
cellisreferencedbythepropertyofCustomerthatshoulddisplay.Whatisparticularly
importantaboutdisplayingthedataisthateachcellusestheHtml.Encodehelpermethod
insteadofdisplayingthedatadirectly.Thisisabestpracticeforbestsecuritytoensure
thatanydatadisplayedisnottreatedasHTMLmarkuporaccidentallyrunsJavaScript
thatyoudidn’tintend.Yousee,amalicioushackercouldaddJavaScriptduringdataentry
andwhenyoudisplaythatfield,thebrowserwouldtrytoruntheJavaScriptcode,which
Chapter9: CreatingWebApplicationswithASP.NETMVC 273
wouldbebad.UsingHtml.Encodepreventsthisfromhappening.TheotherHtmlhelper
methods,suchasActionLink,alreadyencodeoutput,soyoushoulduseHtml.Encode
wheneveroneoftheotherhelpersisn’tused.Noticethatthecodefortheforeachloopis
enclosedin<%and%>symbolssothatitistreatedascodeandnotmarkup.
Next,you’llwanttobeabletonavigatetotheCustomerListpagefromthemain
menu,soopenyourMasterPage,Site.Master,andaddtheCustomersActionLinklikethis:
<ulid="menu">
<li><%=Html.ActionLink("Customers","Index","Customer")%></li>
<li><%=Html.ActionLink("Home","Index","Home")%></li>
<li><%=Html.ActionLink("About","About","Home")%></li>
</ul>
TheparameterstothenewActionLink,fromlefttoright,indicatethatthetextfor
theanchorwillbeCustomers,andASP.NETwillinvoketheIndexactionmethod
ontheCustomerControllerclasswhentheuserclicksthelink.Figure9-6showswhat
theCustomerlistlookslikewhentheprogramruns.
AsshowninFigure9-6,theCustomertabappearsfirstonthelist,andclickingit
showsthelistofCustomers.Inadditiontothecontentyouseeinthelist,therearelinks,
suchasEditandCreate.ThenextsectioncoverstheCreateoperation.
C#:
//
//GET:/Customer/Create
publicActionResultCreate()
{
Customercust=newCustomer
{
Birthday=newDateTime(1980,1,1)
};
returnView(cust);
}
//
//POST:/Customer/Create
[AcceptVerbs(HttpVerbs.Post)]
publicActionResultCreate(Customercust)
{
try
{
if(string.IsNullOrEmpty(cust.Name))
{
ModelState.AddModelError(
"Name","Nameisrequired.");
returnView();
}
Chapter9: CreatingWebApplicationswithASP.NETMVC 275
newCustomerRepository()
.InsertCustomer(cust);
returnRedirectToAction("Index");
}
catch
{
returnView();
}
}
VB:
'
'GET:/Customer/Create
FunctionCreate()AsActionResult
DimcustAsNewCustomerWith
{
.Birthday=NewDateTime(1980,1,1)
}
ReturnView(cust)
EndFunction
'
'POST:/Customer/Create
<HttpPost()>_
FunctionCreate(ByValcustAsCustomer)AsActionResult
Try
IfString.IsNullOrEmpty(cust.Name)Then
ModelState.AddModelError(
"Name","Nameisrequired.")
EndIf
DimcustRepAsNewCustomerRepository
custRep.InsertCustomer(cust)
ReturnRedirectToAction("Index")
Catch
ReturnView()
EndTry
EndFunction
276 MicrosoftVisualStudio2010:ABeginner’sGuide
IntheHTTPprotocol,therearedifferenttypesofverbsfortheoperationbeingconducted.
Listing9-9demonstratestwooftheseverbs,getandpost.Agetistypicallyassociatedwith
readingdata,andapostistypicallyassociatedwithwritingdata.Listing9-9showsbothget
andpostmethodsintheCreatemethodoverloads.InASP.NETMVC,actionmethodsdefault
togetrequestsandyoumustuseanHttpVerbsattributetospecifyapost.
ThegetCreateactionmethodinstantiatesanewCustomerobjectandpassesittothe
View.Whentheuserfillsintheformandsubmits,thepostCreateactionmethodwill
executeandinsertthenewrecordintothedatabase.
NoticehowIchangedtheCreatemethodparameterfromFormsCollectiontoCustomer.
ASP.NETMVCwillautomaticallyreadtheformvaluesandmatchthosevaluesupwith
matchingpropertiesintheobjectpassedtothemethod.Themethodalsocheckstoensure
thatthenameisfilledinandaddsanerrortotheModelState.Wheneveranerroroccurs,
youneedtoreturntothesameViewtoensuretheuserseestheerrorandcancorrectand
resubmit.ASP.NETMVCwillusethiserrortodisplayerrormessagesintheView.To
createtheView,right-clickeitherCreatemethod,selectAddView,andfillinthevaluesas
showninFigure9-7.
TheAddViewscreeninFigure9-7specifiesstrongtypingontheCustomerclass,but
thistimeitselectsCreateastheViewContent.Listing9-10showstheresultingView.
<%@PageTitle=""Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<MyShopCS.Customer>"%>
<asp:ContentID="Content1"ContentPlaceHolderID="TitleContent"
runat="server">
Create
</asp:Content>
<asp:ContentID="Content2"ContentPlaceHolderID="MainContent"
runat="server">
<h2>Create</h2>
<%using(Html.BeginForm()){%>
<fieldset>
<legend>Fields</legend>
<divclass="editor-label">
<%=Html.LabelFor(model=>model.CustomerID)%>
</div>
<divclass="editor-field">
<%=Html.TextBoxFor(model=>model.CustomerID)%>
<%=Html.ValidationMessageFor(
model=>model.CustomerID)%>
</div>
<divclass="editor-label">
<%=Html.LabelFor(model=>model.Name)%>
</div>
<divclass="editor-field">
<%=Html.TextBoxFor(model=>model.Name)%>
<%=Html.ValidationMessageFor(
model=>model.Name)%>
</div>
<divclass="editor-label">
<%=Html.LabelFor(model=>model.Age)%>
</div>
278 MicrosoftVisualStudio2010:ABeginner’sGuide
<divclass="editor-field">
<%=Html.TextBoxFor(model=>model.Age)%>
<%=Html.ValidationMessageFor(
model=>model.Age)%>
</div>
<divclass="editor-label">
<%=Html.LabelFor(model=>model.Birthday)%>
</div>
<divclass="editor-field">
<%=Html.TextBoxFor(model=>model.Birthday)%>
<%=Html.ValidationMessageFor(
model=>model.Birthday)%>
</div>
<divclass="editor-label">
<%=Html.LabelFor(model=>model.Income)%>
</div>
<divclass="editor-field">
<%=Html.TextBoxFor(model=>model.Income)%>
<%=Html.ValidationMessageFor(
model=>model.Income)%>
</div>
<p>
<inputtype="submit"value="Create"/>
</p>
</fieldset>
<%}%>
<div>
<%=Html.ActionLink("BacktoList","Index")%>
</div>
</asp:Content>
TheValidationMessageForHtmlhelperdisplaysanyerrorsthatoccuronthispage.
TheerrormessagesaredisplayedwhenevertheControlleractionmethodaddstheerror
totheModelState.WhentheuserclickstheSubmitbutton,thispagewillpostbacktothe
CreatemethodwiththeAcceptVerbsattributeforpost.Figure9-8showstheCreatescreen
whenrunning.
InadditiontocreatinganewCustomer,youcaneditexistingCustomers,asis
discussednext.
Chapter9: CreatingWebApplicationswithASP.NETMVC 279
C#:
//
//GET:/Customer/Edit/5
publicActionResultEdit(intid)
{
Customercust=
newCustomerRepository()
.GetCustomer(id);
280 MicrosoftVisualStudio2010:ABeginner’sGuide
returnView(cust);
}
//
//POST:/Customer/Edit/5
[AcceptVerbs(HttpVerbs.Post)]
publicActionResultEdit(Customercust)
{
try
{
newCustomerRepository()
.UpdateCustomer(cust);
returnRedirectToAction("Index");
}
catch
{
returnView();
}
}
VB:
'
'GET:/Customer/Edit/5
FunctionEdit(ByValidAsInteger)AsActionResult
DimcustRepAsNewCustomerRepository
DimcustAsCustomer
cust=custRep.GetCustomer(id)
ReturnView(cust)
EndFunction
'
'POST:/Customer/Edit/5
<HttpPost()>_
FunctionEdit(ByValidAsInteger,ByValcustAsCustomer)
AsActionResult
Try
DimcustRepAsNewCustomerRepository
custRep.UpdateCustomer(cust)
Chapter9: CreatingWebApplicationswithASP.NETMVC 281
ReturnRedirectToAction("Index")
Catch
ReturnView()
EndTry
EndFunction
InthegetEditactionmethod,youneedtogetareferencetothecurrentrecord,
indicatedbytheidbeingpassedin,andpassthatreferencetotheViewfordisplay.The
postEditactionmethodacceptsthemodifiedcustomerandpassesittotherepositoryfor
updateinthedatabase.Youshouldalsoright-clickineitheroftheEditmethodsandselect
AddView.MaketheViewstronglytyped,settheclasstoCustomer,andtheContenttype
toEdit.
Thefinaloperationtocompleteisdiscussednext,howtodeleteaCustomer.
Deleting a Customer
ThedefaulttemplateforcreatingalistaddedanActionLinkforDetails,nexttotheEdit
ActionLink.Youcancreatearead-onlydetailspageifyouwant,orjustensurethelistis
intheformatyouwanttoshoweachcustomerrecord,butforourpurposestheDetails
optionisnotnecessary.So,thisexamplereplacestheDetailslinkwithonefordeleting
arecord.Listing9-12showstheDeleteControllermethod,whichreplacestheDetail
Controllermethod.
C#:
//
//GET:/Customer/Delete/5
publicActionResultDelete(intid)
{
newCustomerRepository()
.DeleteCustomer(id);
TempData["Result"]="CustomerDeleted.";
returnRedirectToAction("Index");
}
282 MicrosoftVisualStudio2010:ABeginner’sGuide
VB:
'
'GET:/Customer/Delete/5
FunctionDelete(ByValidAsInteger)AsActionResult
DimcustRepAsNewCustomerRepository
custRep.DeleteCustomer(id)
TempData("Result")="CustomerDeleted."
ReturnRedirectToAction("Index")
EndFunction
Besidesshowinghowtousetherepositoryforperformingthedeleteoperation,there
areacoupleofnewitemsinListing9-12thatyou’llneedtoknowabout:TempDataand
specifyingaView.TempDataisaspecialobjectforholdingdataforasingledisplayof
aView.So,whentheViewdisplays,itcanreadthecurrentvalueofTempData,butthat
samevaluewillnotbeavailableonthenextViewunlesstheControllerexplicitlyloadsit
again.
InalloftheothercallstoView,itwasassumedthataViewnamedaftertheController
methodwouldbereturned,soitwasn’tnecessarytospecifythenameoftheView.
However,wedon’thaveadeleteView,sowespecifyIndexastheViewexplicitly.
Toaccommodatethedeleteoperation,Listing9-13showsthemodificationsonthe
Index.aspxViewforCustomers(locatedunder\Views\Customer).
C#:
...contentremoved
<h2>Index</h2>
<p>
<%if(TempData["Result"]!=null)
{%>
<label><%=Html.Encode(TempData["Result"].ToString())%>
</label>
<%}%>
</p>
<table>
Chapter9: CreatingWebApplicationswithASP.NETMVC 283
...contentremoved
<%foreach(variteminModel){%>
<tr>
<td>
<%=Html.ActionLink("Edit","Edit",
new{id=item.CustomerID})%>|
<%=Html.ActionLink("Delete","Delete",
new{id=item.CustomerID})%>
</td>
...contentremoved
VB:
...contentremoved
<h2>Index</h2>
<p>
<%IfNotTempData("Result")IsNothingThen%>
<label>
<%=Html.Encode(TempData("Result").ToString())%>
</label>
<%EndIf%>
</p>
<p>
<%=Html.ActionLink("CreateNew","Create")%>
</p>
<table>
...contentremoved
<%ForEachitemInModel%>
<tr>
<td>
<%=Html.ActionLink("Edit","Edit",
NewWith{.id=item.CustomerID})%>|
<%=Html.ActionLink("Delete","Delete",
NewWith{.id=item.CustomerID})%>
</td>
...contentremoved
284 MicrosoftVisualStudio2010:ABeginner’sGuide
Listing9-13hascontentremovedtoavoidduplicatingcodeyou’vealreadyseen.Near
thetopofthelisting,youcanseetheifstatementthatwillchecktoseeifthereisavaluein
TempData["Result"](TempData("Result")inVB)andwilldisplaythatvalueinalabelif
present.NexttotheEditActionLink,theDetailsActionLinkhasbeenchangedtoaDelete
ActionLink,passingtheidofthecurrentcustomerbacktotheControllerfordeletion.
Summary
YounowknowtheessentialpartsofMVC:Models,Views,andControllers.Yousawhow
toimplementtherepositorypatternformanagingadataaccesslayerandsimplifythe
code.Thischaptershowedhowtocreatecontrollersandviews.Youalsolearnedabout
routingandhowithelpsmatchURLstocontrollers,actions,andparameters.Finally,there
wasasectionthatdemonstratedhowtoperformCRUDoperationswithASP.NETMVC.
AnotherpopularWebtechnologyisSilverlight,whichgivesyoutheabilitytocreate
richuserexperiences.ThenextchapterhelpsyougetstartedwithSilverlightdevelopment.
Chapter 10
Designing Silverlight
Applications
285
286 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● StartaNewSilverlightProject
● WorkwiththeSilverlightDesigner
● AddControlstoanApplication
● PlaySilverlightVideos
● DeploySilverlightApplications
S ilverlightisaWebtechnologythatallowsyoutoaddarichuserexperiencetoWeb
applications.ItusesXAML,justlikeWPFapplications,butrunsinaWebpage
supportedbyASP.NET.
OtherpartsofthisbookprepareyouforworkingwithSilverlight.SinceSilverlight
usesXAML,youcanreviewAppendixesAandBtogetup-to-speedonXAMLessentials.
SilverlightalsohasmanyfeaturesincommonwithWPF.Therefore,itwouldbeusefulto
reviewChapter8beforereadingthischapter.Whatyou’lllearninthischapterishowVS
helpsyoucreateaSilverlightproject,howtoaddcontrolstotheSilverlightdesigner,and
howtodeploySilverlightapplications.
SimilartoWPFapplications,SilverlightapplicationsstartwithaMainPage.xamlfile
andanApp.xamlfile,whereApp.xamlrunstoinitializetheapplicationandMainPage
.xamlcontainsthedisplaypage.TheWebsiteisatypicalASP.NETMVCapplication,
exceptthatitdoeshaveatestpagethathoststheSilverlightapplication,SilverlightDemo
CSTestPage.aspx(SilverlightDemoVBTestPage.aspxforVB).There’salsoaSilverlight
DemoCSTestPage.html(SilverlightDemoVBTestPage.htmlforVB),whichperformsthe
samefunctionastheSilverlightDemoCSTestPage.aspx(SilverlightDemoVBTestPage
.aspxforVB)hostingSilverlight,exceptthatthe*.htmlversionusesJavaScriptandthe
HTMLobjecttagtohostSilverlight.Listing10-1showsthecontentsofthetestpageand
howithoststheSilverlightapplication.ThereisnoC#orVBversionofListing10-1
becausethecodeisXAML,whichworksexactlythesamewitheitherlanguage.
<%@PageLanguage="C#"AutoEventWireup="true"%>
<!DOCTYPEhtmlPUBLIC
"-//W3C//DTDXHTML1.0Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title>SilverlightDemoCS</title>
<styletype="text/css">
//cssstylesomitted
</style>
<scripttype="text/javascript"src="Silverlight.js"></script>
<scripttype="text/javascript">
functiononSilverlightError(sender,args){
//errorhandlingcodeomitted
}
</script>
</head>
<body>
<formid="form1"runat="server"style="height:100%">
<divid="silverlightControlHost">
<objectdata="data:application/x-silverlight-2,"
type="application/x-silverlight-2"
width="100%"height="100%">
<paramname="source"
value="ClientBin/SilverlightDemoCS.xap"/>
<paramname="onError"value="onSilverlightError"/>
<paramname="background"value="white"/>
Chapter10: DesigningSilverlightApplications 289
<paramname="minRuntimeVersion"value="3.0.40818.0"/>
<paramname="autoUpgrade"value="true"/>
<a
href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40818.0"
style="text-decoration:none">
<imgsrc="http://go.microsoft.com/fwlink/?LinkId=161376"
alt="GetMicrosoftSilverlight"
style="border-style:none"/>
</a>
</object>
<iframeid="_sl_historyFrame"
style="visibility:hidden;height:0px;width:0px;border:0px">
</iframe>
</div>
</form>
</body>
</html>
Listing10-1containsanobjecttagthathoststheSilverlightapplication.Thisobject
taghasvariousparameters,whicharedescribedinTable10-1.
YoucanruntheapplicationandviewtheWebpage,butthereisn’tmuchtoseeyet.
Thenextsectionstartsyouinthedirectionofmakingsomethingusefulhappenwith
SilverlightbyreviewingtheDesigner.
Parameter Description
source In Figure 10-2, you can see a ClientBin folder in the ASP.NET MVC Web
application project. When the Silverlight project builds, VS will take the output
of that project and place it into the ClientBin folder. The output of a compiled
Silverlight project is a *.xap file, which is the same as a compressed *.zip file,
but with a different name. Silverlight loads the *.xap file into the browser at
runtime and runs the application.
onerror Listing 10-1 omitted the contents of the onSilverlightError JavaScript function,
which is called whenever an error occurs in Silverlight.
background Sets the control background.
minRuntimeVersion States that the user must have v3.0.40818.0 or later of the Silverlight plug-in for
this application to run. The user receives an error message if she doesn’t have
the minimum version.
autoUpgrade If the user doesn’t have the minimum version, as specified in minRuntimeVersion,
setting this to true will prompt the user to begin the upgrade process.
1.YourprojectstartsoutwithapagenamedMainPage.xaml,whichyoushouldopenso
thedesignerisshowing.IftheXAMLeditorisshowing,clickontheDesigntabatthe
bottomofthedesignerwindow.
2.You’llhaveadefaultGrid,whichyoucanworkwithinexactlythesamewayas
thedesignerforWPF,discussedinChapter8.YouneedtoensuretheGridhastwo
rows,withthetoprowbeinglargeenoughtofittheMediaElementandthebottom
largeenoughtofitasinglebutton.Hoverovertheleftmarginofthewindowuntil
youseeagridlineappearonthewindow.Movethegridlineverticallyuntilyou’ve
createdtworows,wherethebottomrowislargeenoughtoholdabutton,asshown
inFigure10-3.Clickonthewindowmarginwhenyouhavethegridlinepositioned
whereyouwant.
3.FindtheMediaElementintheToolboxanddragitontothetoprowoftheWindowin
thedesigner.Ifyoufindthatyouhaven’tmadethetoprowlargeenough,grabthegrid
linearrowintheleftmarginanddragitdownsomemore.
4.SettheNamepropertyoftheMediaElementcontroltoVideoPlayer.
Chapter10: DesigningSilverlightApplications 291
5.TheMediaElementcontrolhasaSourcepropertythatyoucansetwiththeURLof
amovie.SettheSourcepropertyoftheMediaElementcontroltohttp://mschnlnine
.vo.llnwd.net/d1/ch9/8/3/7/0/7/4/OfficeVS10SC1_2MB_ch9.wmv,whichisavideo
thatintroducesVS2010.
6.DragaButtonfromtheToolboxtothebottomrowoftheWindowinthedesigner.
7.SettheNamepropertyoftheButtontoStartStopButtonandsettheContentproperty
oftheButtontoStart.
InFigure10-3,youcanseeaGridwithtworows.ThetoprowholdsaMediaElement
controlandthebottomrowholdsabutton.ThenameoftheVideocontrolisVideoPlayer
andthenameofthebuttonisStartStopButton.
Double-clickingtheStartStopButtoncontrolwillgeneratethisClickeventhandlerin
thecode-behindatMainPage.xaml.cs,showninListing10-2.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Net;
usingSystem.Windows;
usingSystem.Windows.Controls;
usingSystem.Windows.Documents;
usingSystem.Windows.Input;
usingSystem.Windows.Media;
usingSystem.Windows.Media.Animation;
usingSystem.Windows.Shapes;
namespaceSilverlightDemoCS
{
publicpartialclassMainPage:UserControl
{
publicMainPage()
{
InitializeComponent();
VideoPlayer.AutoPlay=false;
}
privateboolm_isPlaying=false;
privatevoidStartStopButton_Click(
objectsender,RoutedEventArgse)
{
if(m_isPlaying)
{
VideoPlayer.Stop();
StartStopButton.Content="Start";
m_isPlaying=false;
}
else
{
VideoPlayer.Play();
StartStopButton.Content="Stop";
Chapter10: DesigningSilverlightApplications 293
m_isPlaying=true;
}
}
}
}
VB:
PartialPublicClassMainPage
InheritsUserControl
PublicSubNew()
InitializeComponent()
VideoPlayer.AutoPlay=False
EndSub
Dimm_isPlayingAsBoolean=False
PrivateSubStartStopButton_Click(
ByValsenderAsSystem.Object,
ByValeAsSystem.Windows.RoutedEventArgs)
If(m_isPlaying)Then
VideoPlayer.Stop()
StartStopButton.Content="Start"
m_isPlaying=False
Else
VideoPlayer.Play()
StartStopButton.Content="Stop"
m_isPlaying=True
EndIf
EndSub
EndClass
Bydefault,theMediaElementstartsplayingtheSourcevideoassoonastheapplication
loads,soIsetAutoPlaytofalseinthecode-behindconstructor.Them_isPlayingfield
keepstrackofwhethertheMediaElementisplayingornot.TheClickeventhandleruses
m_isPlayingtotogglebetweenplayingandstopped.
ThisisaquickdemoofhowtoworkwiththeMediaElementcontrol,butthere’smuch
moreyoucando,suchaspausing,trackingbuffering,checkingvideoposition,andmore.
AllyouneedtodoiseithercaptureeventsoftheMediaElementcontrolorusecontrolslike
buttonsandsliderstointeractwithMediaElement,astheexampleshowsinListing10-2.It
wouldbegoodpracticeforyoutotakewhatyou’velearnedhereandaddmorefunctionality
totheMediaElementcontrol.
294 MicrosoftVisualStudio2010:ABeginner’sGuide
withOOB.TheManifestfiledescribesthecontentsofthe*.xapfile.ToenableOOB,
checkthebox“Enablerunningapplicationoutofthebrowser.”ThenclicktheOut-Of-
BrowserSettingsbuttontodisplaythewindowshowninFigure10-5.
TheOOBsettingsinFigure10-5allowyoutosetinformationfortheapplication,
thesizeitwilltakewhenrunning,andvariouslysizediconsthatWindowswilldisplay.
SettingGPUaccelerationallowstheapplicationtotakeadvantageofthelocalhardwareto
optimizegraphics.
AfteryousaveOOBsettingsandruntheapplication,theusercanright-clickthe
applicationrunninginthebrowserandselectInstallSilverlightDemoCSApplicationOnto
ThisComputer,asshowninFigure10-6.
296 MicrosoftVisualStudio2010:ABeginner’sGuide
Thenextwindowyou’llseegivesoptionsforaddingtheapplicationtotheStartmenu
andanicononthedesktop.Figure10-7showsthatbothoptionsarechecked.
WhenyouclickOK,SilverlightcreatesaStartmenuitemandaddstheapplication
tothedesktop,asshowninFigure10-8.Whenyoustarttheapplication,itwillrunina
windowratherthanthebrowser.
1.OpenAdministrativeTools|InternetInformationServices(IIS)Manager.
2.UnderWebSites,inIIS,right-clickontheWebsiteforyourSilverlightapplicationand
selectProperties.
3.ClicktheHTTPHeaderstab,clickMIMETypes,andclickNew.
4.Type.xapastheExtensionandapplication/x-silverlight-appastheMIMEtype.
ClickOKthreetimestocloseallwindowsandcloseIIS.
Additionally,youmusthaveapolicyfileintherootfolderofyourWebsite.There
aretwotypesofpolicyfilesyoucanuse:crossdomain.xmlorclientaccesspolicy.xml.
298 MicrosoftVisualStudio2010:ABeginner’sGuide
Thecrossdomain.xmlpolicywascreatedforAdobeFlashapplicationsandcanbeused
withSilverlightapplicationstoo.Here’sanexample:
<!DOCTYPEcross-domain-policy
SYSTEM"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-fromdomain="*"/>
<allow-http-request-headers-fromdomain="*"headers="*"/>
</cross-domain-policy>
WhendesigningSilverlight,Microsoftrecognizedthatthecrossdomain.xml
filewasn’tflexibleenoughandaddedsupportforanothertypeofpolicycalled
clientaccesspolicy.xml.Here’sanexample:
<?xmlversion="1.0"encoding="utf-8"?>
<access-policy>
<cross-domain-access>
<policy>
<allow-fromhttp-methods="*">"
<domainuri="*"/>
</allow-from>
<grant-to>
<resourcepath="/"include-subpaths="true"/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
Thisclientaccesspolicy.xmllistingallowsalldomainstoaccessallsitecontentthat
isn’talreadysecuredbyothermeans.Youcanrestrictaccessbyreplacingthe*inthe
domainuriwithanallowabledomain.Further,youcanreplacetheresourcepathwitha
pathonthesitetorestrictaccesstospecificfolders.Addmorepolicyelementstothisfile
toaddmoredomainsandpaths.
Summary
ThischapterexplainshowtorunaSilverlightapplication.Youlearnedhowtousethe
MediaElementcontrolandhowtobuildUIsusingthesametechniquesasinWPF.The
OOBfunctionalityallowsyoutorunSilverlightfromyourdesktop.Asectiondescribes
deployingtheSilverlightapplicationtoaWebserver.
We’vediscussedacoupleWebtechnologiesalready:ASP.NETMVCinChapter9and
Silverlightinthischapter.ThenextchaptershowsyouanotherWebtechnology:WCF
Webservices.
Chapter
Deploying Web
11
Services with WCF
299
300 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● CreateaWebService
● DeployaWebService
● WriteaClientThatConsumestheWebService
W indowsCommunicationFoundation(WCF)isa.NETtechnologyforcreatingWeb
services.AWebserviceissoftwarethatprovidesfunctionalitythatcanbeusedby
anyothersoftwareapplication,usinganyprogramminglanguage,onanyhardwareand
operatingsystemthatcancommunicateoveranetwork.
ThefunctionalityofWebservicescanbeeitherpublicorprivate.Examplesofpublic
Webservicesmightbeaweatherservicewhereyouprovidethelocationandyougetback
aforecastdatathatyoucandisplayonyourscreenoranaddressverificationapplication
thatwillvalidateifapostaladdressexistsorsuggestalternatives.Examplesofprivate
Webservicesmightbetheabilityformultipleapplicationsinalargecorporationtocalla
customerWebservicewithacustomerIDandreceivethatcustomer’srecord,orperhaps
anorderingsystemwhereyoucansubmitanewcustomerorderandtheWebservice
wouldprocessthesubmissioninthebackgroundforyou.
What’scommonaboutalloftheexamplesintheprecedingparagraphisthat,regardless
ofpublicorprivate,theWebserviceisusefulformorethanoneapplicationorsystem.
EveryoneneedsthesameservicefromtheWebservice,sowhyshouldeachapplication
re-inventthewheeleverytime?Justsetuponeserviceandeveryonecanworkwiththat
oneservice.
Youmustbewonderinghowsuchabroadclaimcanbemadethatonetechnologyis
accessiblebyanysystemregardlessofplatform,language,orsoftware.TheWebservice
isseparatedfromthecallingsystemviaopenstandardsandawell-definedinterface.There
areubiquitouscommunicationsprotocols,suchasHTTP,anddataformatstandards,such
asXML,thatWebservicescanuse.So,ifbothsystemsthatcommunicateuseHypertext
TransferProtocol(HTTP)andXMLinthesameway,thentheWebservicecanbeuseful.
Forexample,ifanapplicationwerebuiltonaSunworkstationrunningSolaris,saving
datainanOracledatabase,andwritteninJava,itcouldstillcommunicatewithyourWCF
service,whichisonanIntel-basedserver,runningWindows2008,savingdatainSQL
Server,andwritteninVB.Itdoesn’tmatterbecausetheJavasystemwilltranslateits
Chapter11: DeployingWebServiceswithWCF 301
callintoXMLandsendtheXMLdataviaHTTPtotheWCFservice.TheWCFservice
understandstheXMLbecauseitwastheWCFservicethattoldtheJavaapplicationwhat
formattoputtheXMLinto.Ifyou’recuriousabouttheformat,it’scalledWebService
DescriptionLanguage(WSDL),whichisacontract(orinterface)thattellscallershow
topackagetheXMLandwhatoperations(suchasGetWeather)canbecalledontheWeb
service.There’smorethattheWSDLdoesbehindthescenes,buttheprimarypointto
makeisthatclients,suchastheJavaapp,usetheWSDLtopackagetheirXMLandsend
ittotheWCFservice.TheservicetranslatestheXMLintoacalltoamethod,runsthe
method,packagestheresultsbackintoXML(asdefinedbytheWSDL),andsendsthe
resultsbacktotheJavaapplication.Essentially,aWCFserviceusesopenstandardssothat
anyothersystemcanusethosesameopenstandardstocommunicate.
ThischapterwillshowyouhowVShelpsyoucreateWCFservices,howtocreate
aclientthatcommunicateswithaWCFservice,andhowtodeployWCFservices.The
deploymentinformationinthischapterisalsousefultoknowforothertypesofWeb
applications,suchasASP.NETMVCandSilverlight.Let’sstartoffwithcreatingaWCF
project.
TheWCFServiceLibrarystartswithtwofileswithdefaultnamesofIService1.cs
(IService1.vbforVB)andService1.cs(Service1.vbforVB),whichcontainaninterface
andaclassthatimplementsthatinterface.Ifyouneedtobrushuponinterfaces,review
Chapter4becauseaninterfaceisanintegralpartofWCFdevelopment.
{
//NOTE:Youcanusethe"Rename"commandonthe
//"Refactor"menutochangetheinterfacename
//"IService1"inbothcodeandconfigfiletogether.
[ServiceContract]
publicinterfaceICustomerService
{
[OperationContract]
stringGetData(intvalue);
[OperationContract]
CompositeTypeGetDataUsingDataContract
(CompositeTypecomposite);
//TODO:Addyourserviceoperationshere
}
//Useadatacontractasillustratedinthesample
//belowtoaddcompositetypestoserviceoperations
[DataContract]
publicclassCompositeType
{
boolboolValue=true;
stringstringValue="Hello";
[DataMember]
publicboolBoolValue
{
get{returnboolValue;}
set{boolValue=value;}
}
[DataMember]
publicstringStringValue
{
get{returnstringValue;}
set{stringValue=value;}
}
}
}
VB:
'NOTE:Youcanusethe"Rename"commandonthe
'contextmenutochangetheinterfacename"IService1"
'inbothcodeandconfigfiletogether.
<ServiceContract()>
304 MicrosoftVisualStudio2010:ABeginner’sGuide
PublicInterfaceICustomerService
<OperationContract()>
FunctionGetData(ByValvalueAsInteger)AsString
<OperationContract()>
FunctionGetDataUsingDataContract(
ByValcompositeAsCompositeType)AsCompositeType
'TODO:Addyourserviceoperationshere
EndInterface
'Useadatacontractasillustratedinthesamplebelow
'toaddcompositetypestoserviceoperations
<DataContract()>
PublicClassCompositeType
<DataMember()>
PublicPropertyBoolValue()AsBoolean
<DataMember()>
PublicPropertyStringValue()AsString
EndClass
TherearetwotypesinListing11-1:ICustomerServiceandCompositeType.Bothof
thesetypesweregeneratedbyVStoprovideanexampleofhowyoucandefineaservice
contract.Afterexplainingthedefaultcode,we’llmodifythecodetomakeitusablefor
workingwithCustomerobjects.
StartingwiththeICustomerServiceinterface,thetwomostimportantpartsofthecodeare
theServiceContractandOperationContractattributes.TheServiceContractattributestates
thatthisinterfacedefinesacontractforaWCFWebservice.WithouttheServiceContract
attribute,thisinterfacewon’tberecognizedbyWCF.TheOperationContractattribute
specifiesmethodsthatareexposedbytheWCFservice.WithouttheOperationContract
attribute,amethodwillnotbevisibleaspartoftheWCFservice.
AWCFservicemethodcanworkwithanyofthebuilt-intypesforparametersor
returntypes,demonstratedbytheGetDatamethodthattakesanintparameterandreturns
astring.Whenworkingwithcustomtypes,youneedadditionalsyntaxtospecifywhat
partsofthetypearepartofthecontract.Thetypesareparametersandreturntypesofthe
servicemethods,andarepartofthecontractinadditiontotheinterface.
Chapter11: DeployingWebServiceswithWCF 305
TheGetDataUsingDataContractmethodillustratesamethodthatusesacustomtype,
CompositeType,asaparameterandreturntype.Beingacustomtype,CompositeTypehas
attributesthathelpdefineitscontract:DataContractandDataMember.TheDataContract
attributeidentifiesCompositeTypeasatypethatcanbeincludedinaWCFservicecontact.
WithouttheDataContractattribute,atypecan’tbeincludedaspartoftheservicecontract.
TheDataMemberattributedecoratestypemembersthatarepartofthecontractforthis
service.WithouttheDataMemberattribute,atypememberwillnotbevisibleaspartof
thecontract.
WestartedcustomizingthecontractwhenchangingthenameofIService1to
ICustomerService,butweneedtocontinuebydefiningthemethodsthatwillbecome
partoftheCustomerServicecontract:GetCustomers,GetCustomer,InsertCustomer,
UpdateCustomer,andDeleteCustomer.Inpractice,therewillbemoremethodsyou’ll
want,justtocustomizethecontractforthespecialneedsofyourapplication,butthese
methodsdepicttypicalscenariosyou’llfrequentlyencounterandarerepresentativeofany
workyou’llperform.Listing11-2showsthemodificationstoICustomerServicetosupport
customeroperations.AftermakingthechangesinListing2,yourapplicationwon’t
compileuntilyouimplementtheICustomerServiceinterfaceinthenextsection.Please
makethechanges,ifyou’refollowingalong,andkeepreadinguntilthenextsection.
C#:
[ServiceContract]
publicinterfaceICustomerService
{
[OperationContract]
CustomerGetCustomer(intcustID);
[OperationContract]
List<Customer>GetCustomers();
[OperationContract]
intInsertCustomer(Customercust);
[OperationContract]
voidUpdateCustomer(Customercust);
[OperationContract]
voidDeleteCustomer(intcustID);
}
VB:
<ServiceContract()>
PublicInterfaceICustomerService
<OperationContract()>
FunctionGetCustomer(ByValcustIDAsInteger)AsCustomer
<OperationContract()>
FunctionGetCustomers()AsList(OfCustomer)
Chapter11: DeployingWebServiceswithWCF 307
<OperationContract()>
FunctionInsertCustomer(ByValcustAsCustomer)AsInteger
<OperationContract()>
SubUpdateCustomer(ByValcustAsCustomer)
EndInterface
Youalreadyknowhowtospecifyaninterface,andtheprecedingsectionexplainedthe
purposeofServiceContractandOperationContractattributes.Listing11-2showsthatall
youneedtodoisspecifythemethodsthatyouwanttobeincludedaspartofthecontract.
Therearetimeswhenyou’llneedtoreturnacustomtypefromaWCFservice.For
example,ifyouneedtofillinadrop-downlist,allyouneedisakeyforthevalueandaname
forthetext.So,youcancreateacustomCustomerLookupclass,asshowninListing11-3,
thatspecifiesDataContractandDataMemberattributes.Listing11-3demonstrateshowa
customtypecouldbecodedifyoueverneededtodothis.
C#:
[DataContract]
publicclassCustomerLookup
{
[DataMember]
publicintCustomerID{get;set;}
[DataMember]
publicstringCustomerName{get;set;}
}
VB:
<DataContract()>
PublicClassCustomerLookup
<DataMember()>
PublicPropertyCustomerID()AsInteger
<DataMember()>
PublicPropertyCustomerName()AsString
EndClass
308 MicrosoftVisualStudio2010:ABeginner’sGuide
UsingacustomtypeforthepurposeoflookupcontrolsattheUIlevel,suchas
theCustomerLookupclassinListing11-3,opensthepotentialtoonlycommunicate
informationthatisnecessary,ratherthananentireobjectwhereallofthedataisn’tbeing
used.Consideringthepotentialslownessofnetworkcommunication,limitingtheamount
ofinformationtransmittedbetweentheWebserviceandyourapplicationcanincreasethe
performanceofyourapplication.
Nowthatyouhaveacontractinplace,thenextstepiswritingaclassthatimplements
thatcontract.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Runtime.Serialization;
usingSystem.ServiceModel;
usingSystem.Text;
namespaceWcfDemoCS
{
//NOTE:Youcanusethe"Rename"commandonthe
//"Refactor"menutochangetheclassname"Service1"
//inbothcodeandconfigfiletogether.
publicclassCustomerService:ICustomerService
{
publicstringGetData(intvalue)
{
returnstring.Format("Youentered:{0}",value);
}
Chapter11: DeployingWebServiceswithWCF 309
publicCompositeTypeGetDataUsingDataContract(
CompositeTypecomposite)
{
if(composite==null)
{
thrownewArgumentNullException("composite");
}
if(composite.BoolValue)
{
composite.StringValue+="Suffix";
}
returncomposite;
}
}
}
VB:
'NOTE:Youcanusethe"Rename"commandonthe
'contextmenutochangetheclassname"Service1"
'inbothcodeandconfigfiletogether.
PublicClassService1
ImplementsICustomerService
PublicFunctionGetData(
ByValvalueAsInteger)AsString
ImplementsICustomerService.GetData
ReturnString.Format("Youentered:{0}",value)
EndFunction
PublicFunctionGetDataUsingDataContract(
ByValcompositeAsCompositeType)AsCompositeType
ImplementsICustomerService.GetDataUsingDataContract
IfcompositeIsNothingThen
ThrowNewArgumentNullException("composite")
EndIf
Ifcomposite.BoolValueThen
composite.StringValue&="Suffix"
EndIf
Returncomposite
EndFunction
EndClass
310 MicrosoftVisualStudio2010:ABeginner’sGuide
ThemethodsoftheCustomerServiceclassinListing11-4showskeletonimplementations
oftheICustomerServiceinterface.Asyouknow,Listing11-2providednewmethodsto
theICustomerServiceinterface,sothecodeinListing11-4willnotcompilebecauseit
doesn’timplementtheICustomerServicemethods.Tofixthisproblem,deletetheGetData
andGetDataUsingDataContractmethodsfromtheCustomerServiceclass.Thenselectthe
ICustomerServiceidentifierintheCustomerService.csfile,whichwilldisplayanunderline
ontheleftoftheICustomerServiceidentifier.Hoveroverthatunderlinetoopenamenuwith
anoptiontoimplementtheICustomerServiceinterface,whichwillgenerateskeletoncode
foreachmemberoftheICustomerServiceinterfaceinsideoftheCustomerServiceclass.The
defaultmethodimplementationsthrowaNotImplementedExceptionexception,meaning
thatyouneedtowritethecodetoimplementthosemethodsbasedontheICustomerService
interface.Listing11-5showstheimplementationoftheICustomerServiceinterfacein
theCustomerServiceclass.IfusingC#,addthecodetoeachmethod.IfusingVB,which
doesn’thavethesameinterfacerefactoringsupportasC#,addallmethodsandcodetothe
CustomerServiceclassasspecifiedinListing11-5.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Runtime.Serialization;
usingSystem.ServiceModel;
usingSystem.Text;
namespaceWcfDemoCS
{
publicclassCustomerService:ICustomerService
{
publicCustomerGetCustomer(intcustID)
{
varctx=newMyShopDataContext();
varcustomer=
(fromcustinctx.Customers
wherecust.CustomerID==custID
selectcust)
.SingleOrDefault();
Chapter11: DeployingWebServiceswithWCF 311
returncustomer;
}
publicList<Customer>GetCustomers()
{
varctx=newMyShopDataContext();
return
(fromcustinctx.Customers
selectcust)
.ToList();
}
publicintInsertCustomer(Customercust)
{
varctx=newMyShopDataContext();
ctx.Customers.InsertOnSubmit(cust);
ctx.SubmitChanges();
returncust.CustomerID;
}
publicvoidUpdateCustomer(Customercust)
{
varctx=newMyShopDataContext();
varcustomer=
(fromcstinctx.Customers
wherecst.CustomerID==cust.CustomerID
selectcst)
.SingleOrDefault();
if(customer!=null)
{
customer.Age=cust.Age;
customer.Birthday=cust.Birthday;
customer.Income=cust.Income;
customer.Name=cust.Name;
ctx.SubmitChanges();
}
}
312 MicrosoftVisualStudio2010:ABeginner’sGuide
publicvoidDeleteCustomer(intcustID)
{
varctx=newMyShopDataContext();
varcustomer=
(fromcstinctx.Customers
wherecst.CustomerID==custID
selectcst)
.SingleOrDefault();
if(customer!=null)
{
ctx.Customers.DeleteOnSubmit(customer);
ctx.SubmitChanges();
}
}
}
}
VB:
'NOTE:Youcanusethe"Rename"commandonthecontext
'menutochangetheclassname"Service1"inbothcode
'andconfigfiletogether.
PublicClassCustomerService
ImplementsICustomerService
PublicFunctionGetCustomer(ByValcustIDAsInteger)AsCustomer
ImplementsICustomerService.GetCustomer
DimctxAsNewMyShopDataContext
Dimcustomer=
(FromcustInctx.Customers
Wherecust.CustomerID=custID
Selectcust).SingleOrDefault()
Returncustomer
EndFunction
PublicFunctionGetCustomers()AsList(OfCustomer)Implements
ICustomerService.GetCustomers
DimctxAsNewMyShopDataContext
Chapter11: DeployingWebServiceswithWCF 313
Return(FromcustInctx.Customers
Selectcust).ToList()
EndFunction
PublicFunctionInsertCustomer(ByValcustAsCustomer)AsInteger
ImplementsICustomerService.InsertCustomer
Dimctx=NewMyShopDataContext
ctx.Customers.InsertOnSubmit(cust)
ctx.SubmitChanges()
Returncust.CustomerID
EndFunction
PublicSubUpdateCustomer(ByValcustAsCustomer)
ImplementsICustomerService.UpdateCustomer
DimctxAsNewMyShopDataContext
Dimcustomer=(FromcstInctx.Customers
Wherecst.CustomerID=cust.CustomerID
Selectcst).SingleOrDefault()
IfNot(customerIsNothing)Then
Withcustomer
.Age=cust.Age
.Birthday=cust.Birthday
.Income=cust.Income
.Name=cust.Name
EndWith
ctx.SubmitChanges()
EndIf
EndSub
PublicSubDeleteCustomer(ByValcustIDAsInteger)
DimctxAsNewMyShopDataContext
Dimcustomer=(FromcstInctx.Customers
314 MicrosoftVisualStudio2010:ABeginner’sGuide
Wherecst.CustomerID=custID
Selectcst).SingleOrDefault()
IfNot(customerIsNothing)Then
ctx.Customers.DeleteOnSubmit(customer)
ctx.SubmitChanges()
EndIf
EndSub
EndClass
TheimplementationofCustomerServiceissimilartowhatyou’veseeninprevious
chapters.ThedifferenceisthattheimplementationisinaWebservice,whichmustbe
consumeddifferently.We’llsoongettothesectionofthischapterthatshowshowto
consumeaWebservice,butyoumustunderstandthataWebserviceisacomponentthat
youcommunicatewithoveranetwork.Inpreviouschapters,you’veseencodethatworks
withdataintegratedwithapplicationcode.However,Webservicesmustbehostedbya
server,suchasInternetInformationServices(IIS),andconsumingcodemustconnectand
communicatethroughcallstoIIS.Thenextsectionpointsyouintherightdirectionabout
hostingaWebserviceinIIS.
1.SelectStart|ControlPanel|ProgramsAndFeatures,whichwilldisplaytheUninstall
OrChangeAProgramwindow,showninFigure11-3.
2.Clickthe“TurnWindowsfeaturesonoroff”link,whichwilldisplaytheWindows
Featureswindow,showninFigure11-4.
316 MicrosoftVisualStudio2010:ABeginner’sGuide
3.ThisexampleenablesFTP,whichisoneofthewaysyoucandeployaWebsite.Ensure
theoptionfor“EnsureIISMetabaseandIIS6configurationcompatibility,”under
theIIS6ManagementCompatibilitybranch,isselected.WhenyouclickOK,theIIS
serverwillbeinstalled.
1.SelectStart|ControlPanel|AdministrativeTools,whichwilldisplaytheAdministrative
Toolswindow,showninFigure11-5.
2.Double-clickInternetInformationServices(IIS)ManagertodisplaytheInternet
InformationServices(IIS)Managerwindow,showninFigure11-6.
318 MicrosoftVisualStudio2010:ABeginner’sGuide
3.Right-clickSitesandselectAddWebSite,orclicktheAddWebSitelinkonthe
ActionspaneltoshowtheAddWebSitewindow,showninFigure11-7.
4.GivetheWebsiteanameandspecifythephysicallocation.AsshowninFigure11-7,
thenameofthesiteisWcfDemoandthesitewillbephysicallylocatedatc:\WebSites\
WcfDemo.NoticethatthePortintheBindingsectionissetto8080.Thedefaultfora
Websiteportis80,butyoucanhaveonlyasinglesitewiththatport.Alternatively,you
couldchangethehostnameandkeepport80.Inthiscase,wedecidedtosettheportto
8080sothattheaddressesoftheWebsitesdon’toverlap.Useadifferentportnumberif
8080isalreadyusedonyoursystem.ClickingOKwillcreatetheWebsite.
Chapter11: DeployingWebServiceswithWCF 319
5.EnsurethattheWcfDemoWebsiteisselectedinIISManagerandclicktheAddFTP
PublishinglinkontheActionspane,whichisontherightsideofIISManager.You’ll
seetheBindingAndSSLSettingswindow,showninFigure11-8.
6.AcceptthedefaultsontheBindingAndSSLSettingswindowandclickNexttoshow
theAuthenticationAndAuthorizationwindow,showninFigure11-9.
7.SetoptionsontheAuthenticationAndAuthorizationwindowaccordingtowhoyou
wanttobeabletoaccessthisWebsite.Anonymousallowsanyonetoaccessthesite
andislesssecure.Amoresecureoptionwouldbetorestrictaccesstospecifiedusersor
groupsthatyoutrust.Basicauthorizationshowsaloginscreenwhensomeoneconnects
totheFTPsite.ClickingFinishwillenablethissiteforFTPaccess.
320 MicrosoftVisualStudio2010:ABeginner’sGuide
8.InIISManager,selectApplicationPools.Anapplicationpoolisaprocessthatyou
canassignWebsitesto.ThisgivesWebsitesprotectionfromeachotherbecauseif
oneprocesscrashes,itdoesn’tbringdownWebsitesinotherprocesses.IIScreated
anapplicationpoolforyourWebsitewiththesamenamewhencreatingitpreviously.
Double-clicktheapplicationpoolnamedafteryourWebsiteandsetits.NET
Frameworkversiontov4.Theexactversionnumbercouldvaryinthefuture,soyou
wanttoensureit’sthesame.NETFrameworkversionnumberthatyoubuildyour
applicationwithinVS.
OnceyourWebsiteissetup,youcandeploy,whichisdiscussednext.
Chapter11: DeployingWebServiceswithWCF 321
TIP
You must run VS as Administrator to publish. To do this, close VS (if running), locate the
VS Start menu item (don’t click yet), right-click, and select Run As Administrator.
ThetechniqueusedintheprecedingsectiontocreateaWebsitedistinguishedtheWeb
sitebymakingitrunonport8080.AlthoughtheWebsiteisnamedWcfDemo,it’slocated
onthelocalmachine,whosedomainislocalhost.IfyoudeployedtheWebservicetoasite
thatalreadyhadadomain,youwouldusethatdomainname.Forexample,thedomainfor
theC#Stationcommunitysiteiscsharp-station.com,whichisaddressedashttp://www.
csharp-station.com.EachWebserviceatalocationisaddressedbya*.svcfilenameand
thenamethatVScreatesiscalledWcfDemoCS.CustomerService.svc.Puttingthepieces
ofWcfDemositetogetherresultsinanaddressofhttp://localhost:8080/WcfDemoCS.
CustomerService.svc.
Chapter11: DeployingWebServiceswithWCF 323
WhenyoucreateanewWCFServiceproject,VSaddsafilenamedapp.configto
theproject,whichisafilethatbelongsonlytoVS.Theapp.configfileisneverdeployed
withyourWebservice,butitgeneratesafilenamedweb.config,whichisdeployed
withtheproject.InWPFprojects,VSusestheapp.configfiletogenerateafilenamed
projectname.exe.configinthesamefolderastheprojectname.exefile.WCFService
projectsdon’tgenerateaconfigfileintheoutputfolder,buttheydogenerateaweb.config
filewhenyoudeploy.You’llseeweb.configsoon,afterdeployment.
Duringdevelopment,youworkwiththeapp.configfile,whichiseasytofindand
openinyourproject.Theapp.configfilehasalotofinformationinit,soListing11-6isa
smallexcerptthatshowsyouthesalientelementsoftheWCFconfiguration.
<?xmlversion="1.0"encoding="utf-8"?>
<configuration>
...
<system.serviceModel>
<bindings>
...
</bindings>
<client/>
<services>
<servicename="WcfDemoCS.CustomerService">
...
<endpointaddress="mex"binding="mexHttpBinding"
contract="IMetadataExchange"/>
<host>
<baseAddresses>
<addbaseAddress=
"http://localhost:8732/Design_Time_Addresses
/WcfDemoCS/CustomerService/"/>
</baseAddresses>
</host>
</service>
</services>
...
</system.serviceModel>
...
</configuration>
324 MicrosoftVisualStudio2010:ABeginner’sGuide
FollowingthepathinListing11-6—configuration,system.serviceModel,services,
service,host,andbaseAddresses—you’llfindabaseAddresselementinbold.The
baseAddressinListing11-6issplitintotwolinestofitthebook,butremembertocombine
itintoasingleline.ThebaseAddressisdeclaringthatapplicationscancommunicate
withthisserviceviathisaddress.ThisisaVSdevelopmentWebserveraddressthat
wasgeneratedforthisWCFservice.Previously,yousawhowwefiguredoutwhatthe
deploymentaddressofthisapplicationshouldbe.Therefore,whenyoudeploy,comment
outthedevelopmentaddressandreplaceitwiththedeploymentaddress,likethis:
<baseAddresses>
<!--<addbaseAddress=
"http://localhost:8732/Design_Time_Addresses/WcfDemoCS/Service1/"/>-->
<addbaseAddress="http://localhost:8080/WcfDemoCS.CustomerService
.svc"/>
</baseAddresses>
The<!--and-->arecommentdelimiters,andanythinginbetweenthemwon’tbe
interpretedaspartoftheconfiguration.Noticehowthedeploymentaddressisused
(uncommented)asthebaseaddress.Afterdeployment,youcancommentthedeployment
addressanduncommentthedevelopmentaddresssothatyoucancontinueworkingwith
theWCFservicewiththeVSWebserver.
InadditiontothebaseAddress,youneedtoensureyourdatabaseconnectionis
updatedforthedeploymentenvironment.Inthedevelopmentenvironment,thedefault
DBconnectionstringdefaultstousingIntegratedSecurity=trueaslogincredentials,
whichusestheidentityofthecurrentlylogged-inuser.Theresultinthedeployment
environmentisthattheapplicationwillrunastheidentityoftheapplicationpoolthe
Websiteisassignedto.Theproblemwiththisisthattheapplicationpooldoesn’thave
accesstoyourdatabase.Thebestapproachistocreateauserforyourapplicationonly,
givethatuseraccesstoyourdatabase,andthensettheconnectionstringtousethe
credentialsofthatuser.
CreateauserinyourWindowsOSthatwillbeusedforSQLServerandthengive
thatuseraccesstothedatabase.Ifyou’reusinganExpressversionofSQLServer,itcan
helpifyoudownloadthefreeSQLServerExpressManagementStudio.Becauseofallthe
variablesthatcanaffectsettingupsecurity,refertoSQLServerdocumentationformore
guidance.ThischapterusesSQLauthentication,sogoaheadandcreateaWindowsor
SQLuserfortheMyShopdatabase.
Chapter11: DeployingWebServiceswithWCF 325
Withtheuseraccountsetupforthedatabase,updatetheapp.configfileoftheservice
tousethecredentialsofthatuseraccount,likethis.Forbestsecurity,pleaserememberto
changethepassword:
<addname=
"WcfDemoCS.Properties.Settings.MyShopConnectionString"
connectionString=
"DataSource=.\sqlexpress;InitialCatalog=MyShop;
UserID=MyUserAccount;Password=G7b@H8m2a%lM6y;Pooling=False"
providerName="System.Data.SqlClient"/>
Todeploy,right-clicktheWebServicesproject,WcfDemo,andclickPublish,which
willdisplaythePublishWCFServicewindowshowninFigure11-10.
InthePublishWCFServicewindow,settheTargetLocationtotheaddresswherethe
WCFServiceisdeployed.Yousawhowtofigureouttheaddressearlierinthissection.
Youcanchoosetoeitherreplaceonlymatchingfilesordeleteallfilesinthedeployment
location.Younormallyonlywanttocopyfilesneededtorunthisapplicationbecausethe
deploymentwillbequickerwithfewerfilesandpossiblymoresecurebyonlydeploying
whatisnecessary.ThecheckboxforIncludeFilesFromTheApp_DataFolderisdisabled
becausethereisn’tanApp_DatafolderintheWCFServiceproject.However,thissame
toolisusedtodeployanASP.NETWebsite,whichmighthaveanApp_Datafolder.
Normally,youdon’twanttodeploytheApp_Datafolderbecauseitmightholdadatabase
filethatishugeandwouldslowdownyourapplicationconsiderably.Ofcourse,ifyou
haveSQLServerExpressinstalledatthedeploymentlocationandneedthedatabasein
App_Datatobedeployed,checkthisboxtoincludethedatabaseinthedeployment.Click
Publishtodeployyourservice.
Whendeploymentiscomplete,you’llseeamessageontheVSstatusbarstatingeither
PublishSucceededorPublishFailed.Ifpublishingfails,opentheOutputwindow,CTRL-W,
O,toseethereasonwhy.Therearemanyreasonsadeploymentcanfail,solookatthe
errormessagetoseeifit’ssomethingthatmakessensetoyou.VerifythatyourWebsite
isproperlysetup,asexplainedintheprecedingsection.Othersourcesofinformation
includetheMicrosoftDeveloperNetwork(MSDN),athttp://msdn.microsoft.com,where
youcansearchforKnowledgeBasesupportarticles.Alternatively,youcancopytheerror
messageandpasteitintoyourfavoritesearchengine.Manyproblemswithdeployment
surroundIISsetup,soitisworthwhiletolearnmoreabouthowIISworks.McGraw-Hill
offersWindowsServer2008:ABeginner’sGuide,byMartyMatthews(2008),which
doesincludeIIS7information.There’salsoaWindowsServer2003editionifyouare
deployingtoIIS6.
NowthatyouknowhowtodevelopanddeployaWCFservice,you’llneedtoknow
howtowriteprogramsthatusethatservice,whichiscoverednext.
andselectAddServiceReference.You’llseetheAddServiceReferencewindow,
showninFigure11-11.
Asyoumayrecallfrompreviousdiscussioninthischapter,wespentsometimeon
settingupaWebserviceandconfiguringtheWebserviceaddress.Nowtheaddresscomes
intofocusbecauseitiswheretheWebserviceisdeployed—youtypeitintotheAddress
boxintheAddServiceReferencewindow,showninFigure11-11.Ifyouareusingthe
WebserverbuiltintoVStouseaWebserviceprojectinthesamesolution,itisconvenient
toclicktheDiscoverbutton,whichwillgiveyoualistofWebservicesinthesame
solutionastheprojectyouareaddingtheservicereferenceto.TheaddressinFigure11-11
isdifferentfromwhatyou’llseeonyourcomputerbecausetheprojectname,portnumber,
andservicenamewillbedifferent.
IfyouneedtouseadeployedWebservice,youwouldputtheaddressofthedeployedWeb
serviceintheAddressbox.Forexample,earlierinthischapteryousawhowwedeployed
aWebservicetothelocalIISserverandthattousethatdeployedWebserviceyouwould
328 MicrosoftVisualStudio2010:ABeginner’sGuide
puthttp://localhost:8080/WcfDemo.CustomerService.svcintotheAddressbox.Inthe
deployedservice,theservicenamemightnotbeWcfDemo.CustomerService.svcasshown
inthisdemo.Tofindoutwhattherealservicenamefileshouldbe,navigatetothephysical
directorywheretheservicewasdeployedtoandusethefilenameofthe*.svcfile.Sometimes,
you’llneedtouseWebservicesbythirdpartiesoranotherorganizationinyourcompany.In
thosecases,you’llgettheaddresstousefromapersonintheotherorganizationorreadtheir
documentationtolearnwhataddresstouse.Ifyouaddyourownaddress,clickGotogetmore
informationontheWebservice.
AftereitherclickingDiscoveroraddinganaddressandclickingGo,you’llhave
oneormoreservicesintheServiceslist.Atthispoint,ifyoureceiveanerror,itwillbe
becausetheaddressisincorrect,theserviceisexperiencinganoutage,or(inthecase
ofreferencingaserviceinyourownproject)theservicewon’tcompile.Firstcheckthe
addressifyouenteredityourself.Ifyouarereferencingaprojectinyoursolution,goback
andrecompiletheWebServiceprojecttomakesureitbuilds,fixanyproblems,andtry
tocreatetheservicereferenceagain.Onceyou’veensuredthatyou’vecorrectedallthe
problemsonyoursideofthewire,contactwhoeverownstheWebservicetotroubleshoot
theproblem.
WhenaWebservicecanbecommunicatedwithsuccessfully,you’llseethelist
ofservices.Youcandrilldownoneachserviceuntilyoufindtheinterfaceforthe
serviceyou’reinterestedin.InFigure11-11,theICustomerServiceisselected,which
displaysallavailableoperations.Lookingbackatthepreviousdiscussionofcreating
theCustomerService,youcanseetheinterfacethatwascreatedandthemethods.Ifyou
don’tseeaninterfaceoramethod,checktheattributesinthecodetoensuretheinterface
hasaServiceContractattributeandthatanymethodsthatshouldbeexposedhavean
OperationContractattribute.
TheWebservicewillcreateaproxy,whichisaclassthatcommunicateswiththeWeb
service,inyourproject,usingthedefaultnamespacedeclaredinthePropertiesforyour
project.ThenamespaceintheAddServiceReferencedefaultstoService1,andyou’llwant
tochangethattosomethingmeaningful,suchasCustomerService,asshowninFigure11-11.
ThiswillresultinaproxyclasscreatedinMyProjectNamespace.CustomerService.Thisis
importanttoknowbecauseyouwillneedtocreateaninstanceoftheproxyandmustknow
thenamespacethattheproxyresidesin.ClickOKtocreatetheservicereferencesuchasthe
oneshowninFigure11-12.
AsyoucanseeinFigure11-12,theprojecthasanewfolder,namedServiceReferences.
TheCustomerServicereferenceunderServiceReferencesisnamedafterthenamespaceyou
specifiedintheAddServiceReferencewindow.
Chapter11: DeployingWebServiceswithWCF 329
Nowthatyouhaveaservicereference,youcanuseitinany.NETapplication.The
followingsectionshowsyouhowtowritecodetocommunicatewiththeWebservice.
namespaceoftheexamplecodeforthischapterisCustomerConsole,thenamespace
oftheWebserviceproxyisCustomerConsole.CustomerService.Here’scodethat
instantiatestheproxy:
C#:
varsvc=newCustomerServiceClient();
VB:
Dimsvc=NewCustomerServiceClient
Theproxyisnamedaftertheservicereference,withClientappendedtothename.As
withanyotherclass,youinstantiatetheproxy,resultinginareferencetotheproxy,named
svc.Usingtheproxymakesyourcodefeellikeeverythingisinthesameproject,but
reallytheproxymakesacalloverHTTP,sendinganXMLpackagetotheWebservice.
TheWebservicetranslatestheXMLintoamethodcall,executesthecodeforthemethod
call,andtranslatestheresultsbackintoXML.Meanwhile,theproxyiswaitingonthe
WebserviceandwillreceivetheXMLresponse,translatethatresponseintoa.NET
object,andpasstheobjectbacktoyourcallingcode.Ifthemethodreturnsvoidinsteadof
atype,thenthereisn’tanyvaluetoreturn.
Withtheservicereference,youcanbegincommunicatingwiththeWebservice.The
followingexamplecreatesanewcustomerrecord,callingtheInsertCustomermethodon
theWebserviceproxy:
C#:
varnewCust=newCustomer
{
Age=36,
Birthday=newDateTime(1974,8,22),
Income=56000m,
Name="Venus"
};
varnewCustID=svc.InsertCustomer(newCust);
VB:
DimnewCust=NewCustomer
WithnewCust
.Age=36
.Birthday=NewDateTime(1974,8,22)
.Income=56000
Chapter11: DeployingWebServiceswithWCF 331
.Name="Venus"
EndWith
DimnewCustIDAsInteger
newCustID=svc.InsertCustomer(newCust)
Atthispoint,youmightbewonderingwheretheCustomertypecamefrom.Asyou
mayrecallfromtheprevioussectionofthechapterthatdiscussedcustomobjects,the
CustomertypeisaproxytypefortheCustomerthatwasdefinedinLINQtoSQL.Since
wesettheSerializationModeoftheLINQtoSQLentitymodeltoUnidirectional,theWeb
servicewasabletopassthedefinitionoftheCustomerwiththeWebserviceinterface,
resultinginaCustomerproxy.
Toperformtheinsertoperation,usetheserviceproxyreference,svc,topassthe
instanceoftheCustomerproxy.Thefollowingexampleshowshowtogetaspecified
customerfromtheWebservice:
C#:
Customercust=svc.GetCustomer(newCustID);
VB:
DimcustAsNewCustomer
cust=svc.GetCustomer(newCustID)
Here,theserviceproxyreferenceisusedtocallGetCustomerwithanIDoftherequested
customer,returninganinstanceoftheCustomerproxy.Thenextexampleshowshowto
updateaCustomerinstance:
C#:
cust.Income=49000m;
svc.UpdateCustomer(cust);
VB:
cust.Income=49000
svc.UpdateCustomer(cust)
Thecustreferenceinthisexampleisthesamereferencethatwascreatedpreviously.
Inthisexample,weareonlychangingtheIncomeproperty.Next,weusetheservice
proxytocalltheUpdateCustomermethod,passingtheCustomerproxyreference.Ifyou
332 MicrosoftVisualStudio2010:ABeginner’sGuide
wantedtoseethechangesthatweremade,youcouldcalltheGetCustomermethodagain,
likethis:
C#:
CustomerupdatedCust=svc.GetCustomer(cust.CustomerID);
VB:
DimupdatedCustAsCustomer
updatedCust=svc.GetCustomer(cust.CustomerID)
Similarly,youcandeleteaCustomer,asfollows:
C#:
svc.DeleteCustomer(updatedCust.CustomerID);
VB:
svc.DeleteCustomer(updatedCust.CustomerID)
Asinthepreviousexample,weusetheserviceproxyreferencetocalltheDeleteCustomer
method,passinginanIDfromtheupdatedcustomer.TheupdatedCustreferencewasfrom
thepreviouscalltoGetCustomer.IfyouwantedtogetalloftheCustomerrecordsfromthe
Webservice,youcouldcallGetCustomers,likethis:
C#:
Customer[]customers=svc.GetCustomers();
VB:
DimcustomersAsCustomer()
customers=svc.GetCustomers()
Whilethisissimilartoothermethodcallsinpreviousexamples,youmightnoticethat
thereturnvaluefromGetCustomershereisanarrayofCustomer,Customer[](Customer()
inVB).However,theWebservicedefinedGetCustomersasreturningaListofCustomer,
List<Customer>(List(OfCustomer)inVB),asspecifiedintheICustomerService
interfaceinListing11-2andimplementedintheCustomerServiceclassinListing11-5.
Asyoumayrecall,theproxyisresponsiblefortranslatingtheXMLreturnvaluefrom
theWebserviceintoanobject,orcollectionofobjectsinthiscase.Bydefault,theproxy
translatesallcollectionsintoanarray.However,youcanchangethereturncollectiontype
byright-clickingtheServiceReferenceinyourprojectandselectingConfigureService
Reference,showingtheServiceReferenceSettingswindowinFigure11-13.
Chapter11: DeployingWebServiceswithWCF 333
MostoftheitemsintheServiceReferenceSettingsareadvancedoptions,butfocus
ontheCollectionTypesettingintheDataTypesection.SwitchtheCollectionTypefrom
System.ArraytoSystem.Collections.Generic.ListandclickOKtoclose.Thenchangethe
previouscalltoGetCustomerstothefollowing:
C#:
List<Customer>customers=svc.GetCustomers();
VB:
DimcustAsNewCustomer
cust=svc.GetCustomer(newCustID)
334 MicrosoftVisualStudio2010:ABeginner’sGuide
ThisexampleshowsthattheproxywilltranslatetheresultsintoaList<Customer>
(List(OfCustomer)inVB).WhileIshowedyouhowtomakethissettingaftercreating
theWebservice,Ichosethissequencebecauseitshowsthevalueofchangingthe
collectionreturntype.However,youcanmakethissettingwhenfirstcreatingtheWeb
reference.LookingatFigure11-11,youcanseeanAdvancedbuttonatthebottomofthe
AddServiceReferencewindow.ClickingtheAdvancedbuttonwillshowyoutheService
ReferenceSettingswindow,showninFigure11-13,allowingyoutosetthecollection
returntypewhenfirstcreatingtheservicereference.
Now,you’veseenallfiveoperationsoftheWebservice.Rememberthatexactly
thesametechniquesareusedhereasinanyothertypeof.NETapplication.Foryour
convenience,Listing11-7showsyoutheentireexampleforusingaWebservice.
C#:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingCustomerConsole.CustomerService;
namespaceCustomerConsole
{
classProgram
{
staticvoidMain()
{
varsvc=newCustomerServiceClient();
varnewCust=newCustomer
{
Age=36,
Birthday=newDateTime(1974,8,22),
Income=56000m,
Name="Venus"
};
varnewCustID=svc.InsertCustomer(newCust);
Console.WriteLine("NewCustomerID:"+newCustID);
Customercust=svc.GetCustomer(newCustID);
Chapter11: DeployingWebServiceswithWCF 335
Console.WriteLine("NewCustomer:"+cust.Name);
cust.Income=49000m;
svc.UpdateCustomer(cust);
CustomerupdatedCust=svc.GetCustomer(cust.CustomerID);
Console.WriteLine("EconomicAdjustment:"+cust.Income);
svc.DeleteCustomer(updatedCust.CustomerID);
//Customer[]customers=svc.GetCustomers();
List<Customer>customers=svc.GetCustomers();
Console.WriteLine("\nAllCustomers:\n");
foreach(varcustItemincustomers)
{
Console.WriteLine(custItem.Name);
}
Console.ReadKey();
}
}
}
VB:
ImportsCustomerConsoleVB.CustomerService
ModuleModule1
SubMain()
Dimsvc=NewCustomerServiceClient
DimnewCust=NewCustomer
WithnewCust
.Age=36
.Birthday=NewDateTime(1974,8,22)
.Income=56000
.Name="Venus"
EndWith
DimnewCustIDAsInteger
336 MicrosoftVisualStudio2010:ABeginner’sGuide
newCustID=svc.InsertCustomer(newCust)
Console.WriteLine("NewCustomerID:"&newCustID)
DimcustAsNewCustomer
cust=svc.GetCustomer(newCustID)
cust.Income=49000
svc.UpdateCustomer(cust)
DimupdatedCustAsCustomer
updatedCust=svc.GetCustomer(cust.CustomerID)
Console.WriteLine("EconomicAdjustment:"&cust.Income)
svc.DeleteCustomer(updatedCust.CustomerID)
DimcustomersAsList(OfCustomer)
'DimcustomersAsCustomer()
customers=svc.GetCustomers()
EndSub
EndModule
ApplicationType ConfigurationFile
Console App.config
WPF App.config
ASP.NET MVC Web.config
Silverlight ServiceReferences.ClientConfig
Regardlessofthename,eachconfigurationfilewillhaveasystem.serviceModel
elementwithconfigurationsettingsfortheWebservice.Listing11-8showspartsof
theconfigurationfilethatyoushouldfindtochangetheaddressoftheWebserviceto
communicatewith.
<?xmlversion="1.0"encoding="utf-8"?>
<configuration>
<system.serviceModel>
...
<client>
<endpointaddress="http://localhost:8732
/Design_Time_Addresses/WcfDemoCS/CustomerService/"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_ICustomerService"
contract="CustomerService.ICustomerService"
name="WSHttpBinding_ICustomerService">
...
</system.serviceModel>
</configuration>
Followingthepathsystem.serviceModel,client,endpoint,you’llfindanaddress
attribute.Intheprecedingexample,theaddressissettotheaddressoftheWcfDemoproject
insidethesamesolution.Whenyoudeployyourclient,you’llwantittocommunicatewith
thedeployedWebservice.Thefollowingmodificationallowsthisclienttocommunicate
withtheWebservicedeployedtoIISasdiscussedpreviouslyinthischapter:
<endpoint
address="http://localhost:8080/WcfDemoCS.CustomerService.svc"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_ICustomerService"
contract="CustomerService.ICustomerService"
name="WSHttpBinding_ICustomerService">
Theaddressincludesafilename,WcfDemoCS.CustomerService.svc,whichwas
automaticallygeneratedwhendeployingtheWcfDemoservice.Youcanseethenameof
thisfilebylookingatthephysicalfolderwheretheWebserviceisdeployed.
aWebapplicationastheWebserviceclient.However,thismightnotbepossibleifyou
aredeployingtoahostedserverbyathird-partyInternetserviceproviderwhereyou
onlyhaveasingleWebsite.Inthatcase,youhavetheadditionaloptionofaddingaWeb
servicedirectlytoanexistingWebsite.
Toseehowthisworks,createanewASP.NETMVCWebsite.Right-clicktheproject,
selectAdd|NewItem,andcreateanewWCFService.Whatyou’llseeisaninterface
file,IService1.cs;anaddressableservicefile;animplementationclass,Service1.svc;and
Service1.svc.cs,whichyoucanfindundertheService1.svcbranch.Alloftheinformation
you’velearnedpreviouslyinthischapterappliestocodingaWebservicethatispartofthe
Webapplication.Youshouldknowthatthisisanoptionifitfitsyourneeds.
Summary
You’velearnedhowtobuildaWebservice,howtodeploytheWebservice,andhowto
writeaclientthatconsumestheWebservice.ThediscussiononcreatingtheWebservice
showedyouhowtodefinetheWebservicecontractwithaninterfaceandapplicable
attributes.Yousawhowtoimplementtheservicealso.Thedeploymentdiscussion
explainedhowtohostaWebservicewithIISandhowtousetheVSPublishWizardfor
deployment.YoualsosawhowtowriteaclientthatcreatesareferencetoaWebservice
andwritescodetocommunicatewiththeWebservice.
Part IV
Enhancing the VS
2010 Experience
This page intentionally left blank
Chapter
Customizing
12
the Development
Environment
341
342 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● ImplementCustomTemplates
● CreateCustomSnippets
● WriteMacros
I nadditiontoallthegreatfeaturesyou’veseeninprecedingchapters,VSgivesyouthe
capabilitiestocustomizeyourownenvironment.ThecustomizationsI’lldiscussare
customtemplates,customsnippets,andmacros.
Throughoutthebook,you’vestartednewprojectsandaddeditemstothoseprojects,
usingwhatisavailablewithVS.Onsomeoccasions,youmightdesiretohaveaspecial
typeofprojectorcustomizeanexistingprojectforyourownneeds.Thesameneedmight
applytoprojectitems(suchasaspecialtypeofclassfile),whereyoumightchangethe
contentsofanitemorcreateanewitem.
Chapter2showedyouhowtousesnippets,andChapters3and4showedhowtouse
severalmoresnippetstoquicklycodecommonstatements.Inadditiontousingexisting
snippets,youcancreateyourown.VSalsohasamanagementwindowthatallowsyouto
organizesnippets,adding,deleting,andrearrangingasyouseefit.
Wheneveryourunintorepetitivescenarios,itwouldbenicetocapturetheactions
youperformsothatyoucanquicklycompleteatask.Forexample,ifyoufoundyourself
usingthesamesetofkeystrokes,itwouldbenicetocollapsethatactiondownintoone
command.Macrosallowyoutocollapserepetitivetasksintoasingletask,savingyoutime.
Let’sstartthejourneyofcustomizingVSbylookingatcustomizingtemplates.
Modifying a Project
Theeasiestwaytogetstartedwithcreatinganewprojecttemplateistostartanewproject
thatismostsimilartotheprojecttypeyouwanttocreate.Ifyouwantedablankproject,
youmightstartwithaConsoleprojectbecausetherearen’tmanyitemsandit’squickerto
deletethemall.Inthescenarioforthissection,wewanttocreateaspecializedASP.NET
MVCproject,soitmakessensetocreateanewASP.NETMVCproject.Thefollowing
stepsshowyouhow:
1.PressCTRL-SHIFT-NtocreateanewprojectandselectASP.NETMVC2WebApplication.
NametheprojectandsolutionCustomASP.NETMVCWebApplicationandsetthe
locationforanywhereyoulike.ClickOKtocreatetheproject.Next,theCreateUnit
TestProjectwindowwillappearandyoushouldclick“No,donotcreateaunittest
project”andclickOK.VSwillcreateanewsolutionwithaproject.Chapter9explains
whateachoftheprojectsanditemsare.
2.OpentheControllersfolderanddeleteitscontents.
3.OpentheModelsfolderanddeleteitscontents.
4.OpentheViewsfolderbutonlydeletetheAccountandHomefolders.
5.OpentheSharedfolder,undertheViewsfolder,anddeleteitscontents.
6.Double-clickGlobal.asaxandcommentoutthecalltoroutes.MapRouteintheeditor.
344 MicrosoftVisualStudio2010:ABeginner’sGuide
7.Tomakesureyourchangesareokay,buildandruntheproject.SelectBuild|Rebuild
Solutionandensureyoudon’treceivecompilererrors.ThenpressF5torunandallow
VStomodifytheWeb.configfile.Sinceyou’vecommentedouttherouteinGlobal
.asaxandtherearen’tanyfilestolocate,you’llreceivethemessage“Theresourcecan’t
befound”inthebrowser.Thisisokaybecauseit’sassumedthatyouwanttobuildyour
owncontrollers,models,andviewsandapplycustomroutingtoo.
YounowhavecustomizedASP.NETMVCprojectthatallowsyoutobuildyour
applicationwithoutanypreinstalleditems.VSislikelytoshipwithanemptytemplate,
butforadditionalcustomization,youmightreplacetheCSSfileintheContentfolder
oraddyourownJavaScriptlibrariestotheScriptsfolder.Makeanychangesyoufeel
aremosthelpfulforstartinganewASP.NETMVCproject.Next,you’lllearnhowto
transformthisprojectintoareusableprojecttemplate.
ThenextwindowisSelectTemplateOptions,showninFigure12-2.TheTemplate
Namedefaultstothenameoftheproject,whichyoucanchange.Youcanseehowthe
filled-inTemplatedescriptiontellswhatthetemplateisusedfor.Additionally,ifyouwant
toassociateaniconorpreview,youcanclicktherespectiveBrowsebuttonandselect
theimageyouwanttobeassociatedwiththeproject.Asyoumayrecall,theNewProject
windowhasaniconfortheprojectandwilldisplayapreviewwheneveryouselectthe
project.The“AutomaticallyimportthetemplateintoVisualStudio”optionwillmakethe
projecttemplateavailableviatheNewProjectwindow.“Displayanexplorerwindowon
theoutputfilesfolder”willallowyoutoaccessthenewfile,shownintheOutputlocation.
ClickFinishtocreatethetemplate.
AfteryouclickFinish,VSdoestwothings:itsavestotheoutputlocationandmakesthe
templateavailableinVS.Theoutputlocationisjustaplacetostoretheprojecttemplate,
CustomASP.NETWebApplication.zip,whichcontainsalloftheinformationVSneeds
todisplaythetemplateandcreatetheprojectifyouselectitintheNewProjectswindow.
Youcansharetheprojecttemplatewithotherdeveloperstoo.Thenextsectionshowswhat
todotogettheprojecttemplatetoappearinVS.
Prompt(2010)andselectRunAsAdministrator.Thiswilltakeafewminutestorun,but
afterwardyou’llseetheprojectappearintheVSNewProjectwindow.Thiscommand
importsalloftheprojecttemplatesfromtheglobalprojecttemplatesfolderintoVS:
devenv/installvstemplates
Iflateryoudecideyoudon’twantagiventemplatetoappearintheVSNewProject
window,removetheprojecttemplatefromtheglobalprojecttemplatesfolder(s)andrun
theprecedingcommandagain.
Nowyou’reabletocreateandusecustomprojecttemplates.Whileyoumightcreate
projectsoccasionally,it’sacommontasktocreateprojectitems,coverednext.
1.PressCTRL-SHIFT-NtocreateanewprojectandselectConsoleApplication.Name
theprojectanythingyouwantandsetthelocationforanywhereyoulike;nameand
locationdon’tmatterbecauseweareonlyinterestedintheitemtemplatefileandnot
theproject.ClickOKtocreatetheproject.VSwillcreateanewsolutionwithaproject.
Bynow,you’veseenplentyofnewConsoleapplicationsinpreviouschapters,andthis
willbethesame.
2.Right-clicktheprojectinSolutionExplorer,selectAdd|NewItem,selectCodeFile,
namethefileEnum.cs(Enum.vbforVB),andclickAdd.Thiswilladdanewblank
filetoyourproject.
348 MicrosoftVisualStudio2010:ABeginner’sGuide
3.Addthefollowingcodetothefile:
C#:
///<summary>
///Enumdescription
///</summary>
publicenumMyEnum
{
///<summary>
///Item1description
///</summary>
Item1,
///<summary>
///Item2description
///</summary>
Item2
}
VB:
'''<summary>
'''Enumdescription
'''</summary>
PublicEnumMyEnum
'''<summary>
'''Item1description
'''</summary>
Item1
'''<summary>
'''Item2description
'''</summary>
Item2
EndEnum
4.Savethefile.
Younowhaveafilethatcanbeusedasaskeletonfornewenums.Thenextsection
showsyouhowtoexportthisfilesothatitcanbeusedasanitemtemplate.
ThenextwindowisSelectItemToExport,showninFigure12-4.Thelistshowsall
ofthefileseligibleforcreatinganitem.CheckEnum.cs,whichistheonlyfilewe’re
interestedinforthisexample.ClickNexttocontinue.
Next,you’llseetheSelectItemReferenceswindow,showninFigure12-5.Theseare
theassembliesthatarepartoftheprojectthatyou’reextractingtheitemtemplatefrom.
Checktheassembliesthatthisitemwillrequire.Inthiscase,IwanttoensuretheSystem
assemblyisincluded.Ignorethewarningmessage,asitisassumedthatyouwillalways
havethe.NETFrameworkinstalledandtheSystem.dllassemblywillalwaysbeavailable.
ClickNexttocontinue.
350 MicrosoftVisualStudio2010:ABeginner’sGuide
Figure12-6showsSelectTemplateOptions,whereyouspecifyhowtheitem
templatewillappearintheNewItemswindowthatappearswhenselectingAdd|
NewItemonaproject.TheTemplatenamedefaultstothenameoftheproject,which
youshouldchangetotheitemname,bychangingthetemplatenametoEnum.The
descriptionletstheuserknowthepurposeoftheitemtemplate.Ifyouwanttoassociate
aniconorpreview,youcanclicktherespectiveBrowsebuttonandselecttheimage
youwanttobeassociatedwiththeitem.Asyoumayrecall,theNewItemwindow
hasaniconfortheitemandwilldisplayapreviewwheneveryouselecttheproject.
The“AutomaticallyimportthetemplateintoVisualStudio”optionwillmaketheitem
templateavailableviatheNewItemwindow.“Displayanexplorerwindowontheoutput
filesfolder”willallowyoutoaccessthenewfile,shownintheOutputlocation.Click
Finishtocreatetheitemtemplate.
Chapter12: CustomizingtheDevelopmentEnvironment 351
AfteryouclickFinish,VSdoestwothings:itsavestotheoutputlocationandmakes
thetemplateavailableinVS.Theoutputlocationisjustaplacetostoretheitemtemplate,
Enum.zip,whichcontainsalloftheinformationVSneedstodisplaythetemplateand
createtheitemifyouselectitintheNewItemwindow.Youcansharetheitemtemplate
withotherdevelopers,too.Thenextsectionshowswhattodotogettheitemtemplateto
appearinVS.
itemtemplatesfolder,youcanverifythatit’sbeenimportedintoVSbyselectinganopen
projectinSolutionExplorer(openaneworexistingprojectifoneisnotopened),pressing
CTRL-SHIFT-A,andobservingthatEnumappearsinthelistintheNewItemwindow.
Ifyouhadnotchecked“AutomaticallyimportthetemplateintoVisualStudio”
(Figure12-6),thenyoucouldhavecopiedtheEnum.zipfiletothelocalprojecttemplates
folderyourselfandtheprojecttemplatewouldappearinVS.IfyoushareEnum.zipfile
withanotherdeveloper,hecancopytothelocalitemtemplatesfolderalso.
Ifyoudeletethefilefromthelocalitemtemplatesfolder,itwillnolongerappearin
theVSNewItemwindow.
Anotheroptionforaddingitemtemplatesistocopytheprojecttemplatesfiletoa
folderunder\ProgramFiles\MicrosoftVisualStudio10.0\Common7\IDE\ItemTemplates,
whichI’llcallglobalitemtemplates.Therearevariousfoldersunderglobalitemtemplates,
Chapter12: CustomizingtheDevelopmentEnvironment 353
includingCSharpVisualBasic,Web,andmore,eachfoldercorrespondingtofoldersinthe
VSNewItemwindow.Undereachfolderisalocalecode—forinstance,Englishis1033—
andyouwouldcopythefileintothelocalefolderforthecategoryyouwantedtheproject
templatetoappearin.
Unliketemplatesinthelocalitemtemplatesfolder,whereallyouneedtodoiscopy
thefile,itemtemplatesintheglobalitemtemplatesfolderdon’tautomaticallyshowup.
Totesttheglobalitemtemplatesscenario,youshouldremovetheitemtemplatefrom
yourlocalitemtemplatesfolder.YoumustclosedownVSandexecutethefollowingina
commandwindow,whichyoushouldopenbyselectingStart|AllPrograms|Microsoft
VisualStudio2010|VisualStudioTools|right-clickVisualStudioCommandPrompt
(2010)andselectRunAsAdministrator.Thiswilltakeafewminutestorun,butafterward
you’llseetheprojectappearintheVSNewItemwindow.Thiscommandimportsallof
theitemtemplatesfromtheglobalitemtemplatesfolderintoVS:
devenv/installvstemplates
Iflateryoudecideyoudon’twantagiventemplatetoappearintheVSNewItem
window,removetheitemtemplatefromtheglobalitemtemplatesfolder(s)andrunthe
precedingcommandagain.
ThissectionshowedyouhowtoaddnewprojectanditemtemplatestoVS,but
sometimesyoujustwanttoaddacommonbitofcodewhileyou’reprogramming.The
nextsectionshowsyouhowtoaddyourowncustomcodesnippetstoVS.
<?xmlversion="1.0"encoding="utf-8"?>
<CodeSnippetsxmlns=
"http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippetFormat="1.0.0">
<Header>
<Title>for</Title>
<Shortcut>for</Shortcut>
<Description>Codesnippetfor'for'loop</Description>
<Author>MicrosoftCorporation</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
<SnippetType>SurroundsWith</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>index</ID>
<Default>i</Default>
<ToolTip>Index</ToolTip>
</Literal>
Chapter12: CustomizingtheDevelopmentEnvironment 355
<Literal>
<ID>max</ID>
<Default>length</Default>
<ToolTip>Maxlength</ToolTip>
</Literal>
</Declarations>
<CodeLanguage="csharp"><![CDATA[for(int$index$=0;
$index$<$max$;$index$++)
{
$selected$$end$
}]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
AsshowninListing12-1,asnippetisanXMLfilewherealldataisdefinedbybegin
andendtagsarrangedinahierarchy.InsideoftheCodeSnippettagsareHeaderand
Snippetelements.
InsideoftheHeaderelementisaShortcutelementthatdefinestheprefixyoumust
typeintheVSeditortousethesnippet.TheTitleandDescriptiontagsdefinewhatdisplays
forIntellisenseinVSwhentheshortcutisbeingtyped.Authortellswhowrotethesnippet.
TheSnippetTypeselementdefinesthetwowaystouseasnippet:Expansionand
SurroundsWith.Chapter2describesmanysnippetsthatworkviaExpansion.However,
SurroundsWithsnippetsarealsoveryuseful.TouseaSurroundsWithsnippet,highlightthe
codethatyouwanttosurround,pressCTRL-SPACE,andselectthesnippet.Afterselecting
thesnippet,thesnippettemplatewillappearinVS,withitsblockssurroundingthe
highlightedtext.Sincetheforloophasablockthatcancontainstatements,itmakessense
thattheforsnippetisbothaSurroundsWithandExpansionsnippet.
TheSnippetelementinListing12-1containsaDeclarationsandCodeelement,wherethe
declarationsareusedinthecode.Thinkingabouthowsnippettemplateswork,rememberthat
yourcursorispositionedonblocksofcodethatyouchangeandtabthroughtocompletethe
snippet.TheblocksofcodetobefilledincorrespondtoLiteralelementsinthedeclaration.
EachLiteralelementhasanIDthatisusedintheCodetodefinewheretheLiteralis
located.Defaultdescribesthedatashowninthetemplatebeforeyoustarttyping.Whenever
you’refillinginasnippettemplate,youcanhoveroverthedatafieldandatooltipwill
describewhatinformationshouldgointothedatafield.ThistooltipisdefinedintheTooltip
elementofthesnippetdefinition.TheIDofeachliteralisdefinedintheCodeelement.
InsidetheCodeelementisthecodeforthesnippet.Thevariablesinthecodewith
$prefixandsuffixhelpdefinehowthesnippettemplateworks.Noticethat$index$
and$max$matchLiteralelementsintheDeclarationselement;thisiswhereyoumust
356 MicrosoftVisualStudio2010:ABeginner’sGuide
fillindataitemswhenfillinginthesnippettemplateinVS.The$end$variabledefines
wherethecursorendsupafterthesnippetiscomplete(afterpressingENTERinthesnippet
template).You’llwanttolocate$end$whereadeveloperwouldnormallycontinuetyping.
The$selected$variableisusedwithSurroundsWithsnippets,definingtherelationshipof
selectedtextwithwheresnippetcodeshouldbe.
Nowthatyouhaveabasicfamiliaritywithsnippets,thenextsectionbringsyoutothe
nextlevelasyouactuallycreateanewsnippet.
1.WithVSopen,pressCTRL-NandcreateanewXMLfile.Ifyouwereopeningthefile
fromanexistingproject,youwouldneedtoprovideaname,whichwouldbemeth
.snippet.ThenewXMLfilehasasingleline,whichiscalledanXMLprefix.
2.MovetothelinebelowtheXMLprefix,pressCTRL-K-X,typesntoselectSnippetinthe
Intellisenselist,andpressENTER.You’llseeanXMLsnippettemplatewiththevalues
forTitle,Author,Shortcut,Description,ID,andDefault.
3.Fillindataandtabthroughthesnippettemplateasfollows:TitleasMethodSnippet,
Authoras<yourname>,Shortcutasmeth,DescriptionasCreateaNewMethod,ID
asaccess,andDefaultaspublic.PressENTERwhencomplete.
4. Theresultingsnippetstillneedscodeandtemplateitemdefinitions,whichisaccomplished
byfillingintheCodeelementandaddingneededLiteralelements.First,modifythecode
elementasfollows:
<CodeLanguage="csharp">
<![CDATA[$access$$return$$methodName$($paramList$)
{
$end$
}
]]>
</Code>
Chapter12: CustomizingtheDevelopmentEnvironment 357
5.Inadditiontoaccess,thecodeexampleintheprecedingstepincludesvariablesfor
return,methodName,andparamList.AddLiteralelementsforeachofthesevariables,
wheretheIDisthevariablenameandtheDefaultissettoreturnasvoid,methodName
asMethodName,andparamListasintp1.
6. Savethefileandnameitmeth.snippet.Thenextsectionwillexplainwheretoputthe
file,butfornowputitinalocationthatyoucanremembersoyoucancopyitlater.
BTW,theSaveFiledialogboxhasSnippetFiles(*.snippet)foraSaveATypeoption,
whichyoucanusetoensurethesnippethasthecorrectfileextension.
Younowhaveaworkablesnippet.Listing12-2showsthesnippetinitsentirety.
Additionally,noticehoweachLiteralhasaTooltiptohelptheuserofthesnippetfillin
eachdataitem.Also,noticethattheLanguageattributeoftheCodeelementisspelled
csharp,ratherthanC#.Thesesmallnuances,suchasthespellingforalanguage,could
makethesnippetfileinvalid.Agoodtroubleshootingtechniqueistoopenasimilar
snippetpredefinedforVS,asdescribedintheprecedingsection,andcompareformatsto
seeifyoumighthavemistypedsomething.Thenextsectionwillexplainwhattodowith
thissnippetfilesothatyoucanbeginusingit.
<?xmlversion="1.0"encoding="utf-8"?>
<CodeSnippetFormat="1.0.0"
xmlns="http://schemas.microsoft.com
/VisualStudio/2005/CodeSnippet">
<Header>
<Title>MethodSnippet</Title>
<Author>JoeMayo</Author>
<Shortcut>meth</Shortcut>
<Description>CreateaNewMethod</Description>
<SnippetTypes>
<SnippetType>SurroundsWith</SnippetType>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>access</ID>
<Default>public</Default>
<ToolTip>Accessmodifier</ToolTip>
</Literal>
358 MicrosoftVisualStudio2010:ABeginner’sGuide
<Literal>
<ID>return</ID>
<Default>void</Default>
<ToolTip>Returnvalue</ToolTip>
</Literal>
<Literal>
<ID>methodName</ID>
<Default>MethodName</Default>
<ToolTip>NameofMethod</ToolTip>
</Literal>
<Literal>
<ID>paramList</ID>
<Default>intp1</Default>
<ToolTip>
Comma-separatedlistofparameters
</ToolTip>
</Literal>
</Declarations>
<CodeLanguage="csharp">
<![CDATA[
$access$$return$$methodName$($paramList$)
{
$end$
}]]>
</Code>
</Snippet>
</CodeSnippet>
10.0\.You’llseelanguagetechnologyfolders,suchasVC#forC#orVBforVB.Within
thosefolders,you’lleitherseefoldersforlanguagecodes(Englishis1033)oraSnippets
folder.Drillingdowntwolevels,throughthelanguagecodefoldersandSnippetfolders
(whichevershowsfirst),you’llseemoresnippetsandsubfoldersthatorganizethesnippets
forthatlanguage/technology.Copythesnippetintothefolderwhereyoufeelitbelongs.
Thesnippetwillbeimmediatelyavailabletoyourcode.
Workingwithsystemfilefolderscanbecumbersome,soVSoffersatooltohelp
organizesnippets,theSnippetsManager.
Writing Macros
WhentheproductivityfeaturesthatshipwithVSandcustomsnippetsdon’tgiveyou
enoughpower,thenextstepistoconsidercreatingamacro,whichisarepeatablesetof
actionsthatyoucanrecordandre-runmultipletimes.Anexampleofwhenamacrois
usefuliswheneveryoufindyourselfcontinuouslyrepeatingthesamesetofactionsinVS.
ThissectionwillshowyouhowtocreateandrunamacrothatusesVSfeaturestocreatea
customizedblockofcodeforvalidatingstrings.
Recording a Macro
Whencreatingbusinessobjects,it’scommontovalidateinputparameterstoensurethey
arevalid.Onesuchvalidationisenforcingthatcallingcodepassarequiredparameter.
Theexampleinthissectionshowsyouhowtowriteamacroforvalidatingthatastring-
typeparameterisnotnull,empty,orwhitespace(suchasaspaceortab).Togetstarted,
createanewConsoleprojectandaddaClassfilewiththefollowingmethodtotheproject,
whichsimulatesaddinganewcustomer:
C#:
usingSystem;
classCustomer
{
publicintAddNewCustomer(stringfirstName,stringlastName)
{
intnewCustID=0;
//Logictoaddcustomer
returnnewCustID;
}
}
VB:
PublicClassCustomer
FunctionAddNewCustomer(
ByValfirstNameAsString,
ByVallastNameAsString)AsInteger
DimnewCustIDAsInteger=0
'Logictoaddcustomer
Chapter12: CustomizingtheDevelopmentEnvironment 361
ReturnnewCustID
EndFunction
EndClass
ThepointofinterestintheAddNewCustomermethodisthefirstNameandlastName
parameters.Wheneverworkingwithdata,you’llusuallywanttoensurethatinputdatais
legal.Whenuserinputisbeingprocessed,it’scommontogetbadinformation,evenifyou
havegoodinputvalidationinyouruserinterfacecode.Forexample,thefollowingcode
callstheprecedingAddNewCustomermethod,passinginbaddataasarguments:
C#:
classProgram
{
staticvoidMain()
{
stringfirstName="Joe";
stringlastName=null;
Customercust=newCustomer();
cust.AddNewCustomer(firstName,lastName);
}
}
VB:
ModuleModule1
SubMain()
DimfirstNameAsString="Joe"
DimlastNameAsString=Nothing
DimcustAsNewCustomer
cust.AddNewCustomer(firstName,lastName)
EndSub
EndModule
Intheprecedingexample,firstNameisokaybecauseithasagoodnameinit.
However,noticethatlastNameissettonull(NothinginVB).Thiswouldcause
aNullReferenceExceptionifAddNewCustomertriedtocallastringoperationon
theparameter,thecodethatAddNewCustomercallscouldpotentiallythrowa
NullReferenceException,or(assumingthatnullisconsideredinvalidinthiscase)you
362 MicrosoftVisualStudio2010:ABeginner’sGuide
couldendupsavingbaddata.SinceAddNewCustomerdoesn’thaveanimplementation,
thisisallspeculation,butthisoutlinesafewofthemanyproblemsthatcanoccurifyou
allowyourbusinessobjectstoacceptdatathatisbadforyourprogram.
Themacrodemonstratedinthissectionwillshowhowtocheckastringparameter
fornull,empty,orwhitespaceandthrowanArgumentNullException.Thiswillprevent
callersfrompassingbaddataandgivethemameaningfulmessage.Tocreateamacro,
youwillneedtolocatethepositioninthecodewherethemacrostarts(ifapplicable),
startrecording,performVSactions,andstoprecording.It’ssomewhatlikeusingavideo
recorderwhereyouhavetofindaTVshow,starttherecording,allowtheshowtoplay,and
thenstoprecording.Performthefollowingstepstocreatetheparametervalidationmacro:
1.ClickthefirstNameparameteroftheAddNewCustomermethodsothatthecursoris
insideofthefirstNameparameteridentifier.Thisisimportantbecauseweneedthe
parameternameinthecode.
2.StartthemacrorecorderbyselectingTools|Macros|RecordTemporaryMacroorpress
CTRL-SHIFT-R.
3.ForC#,pressCTRL-LEFTARROW,CTRL-SHIFT-RIGHTARROW,andCTRL-C.ForVB,press
CTRL-LEFTARROW,CTRL-SHIFT-RIGHTARROW,SHIFT-LEFTARROW,andCTRL-C.Thiscopies
theparametername.
4.ForC#,pressCTRL-FtobringuptheFindAndReplacewindow,type{intoFindWhat,
clickFindNext,ClosetheFindAndReplacewindow,pressEND,andpressENTER.For
VB,pressENDandpressENTER.Thispositionsthecursortobeginenteringcode.
5.TypeifandpressTABtwice(theifsnippet),typestring.IsNullOrWhiteSpace(intothe
condition,pressCTRL-Vtopastetheparameternameastheargument,andtype).For
C#,pressENTER.ForVB,pressDOWNARROW.Thecursormovestothebodyoftheif
statement(asyouwouldexpectwiththeifsnippet).Thissetsupthevalidationcheck
fortheparameter,seeingifitisnull(NothinginVB),anemptystring,orsomewhite
spacecharactersuchasspaceortab.
6.TypethrownewArgumentNullException(",pressCTRL-Vtopastetheparameter
name,type",",pressCTRL-Vtopastetheparametername,typeaspace,andtypevalue
isnotvalid.").ForC#,addasemicolon,;,totheendoftheline.Thisistheactionto
performwhenthevalueisnotvalid,throwinganexceptiontoletthecallerknowthat
thevalueisnotgood.
7.PressDOWNARROWandpressENTER.Thispositionsthecursorafterthecode,which
mightbeconvenientifyouwanttocontinuetypingfromthispoint.
8.SelectTools|Macros|StopRecordingTemporaryMacroorpressCTRL-SHIFT-Rtostop
recording.
Chapter12: CustomizingtheDevelopmentEnvironment 363
You’venowrecordedamacro.Tochecktheprecedingstepsagainstwhatyou’ve
produced,here’sarevisedAddNewCustomermethod,showingwhattheresultsshould
looklike:
C#:
usingSystem;
classCustomer
{
publicintAddNewCustomer(stringfirstName,stringlastName)
{
if(string.IsNullOrWhiteSpace(firstName))
{
thrownewArgumentNullException(
"firstName",
"firstNamevalueisnotvalid.");
}
intnewCustID=0;
//Logictoaddcustomer
returnnewCustID;
}
}
VB:
PublicClassCustomer
FunctionAddNewCustomer(
ByValfirstNameAsString,
ByVallastNameAsString)AsInteger
IfString.IsNullOrWhiteSpace(firstName)Then
ThrowNewArgumentNullException(
"firstName",
"firstNamevalueisnotvalid.")
EndIf
DimnewCustIDAsInteger=0
'Logictoaddcustomer
ReturnnewCustID
EndFunction
EndClass
364 MicrosoftVisualStudio2010:ABeginner’sGuide
Intheprecedingcode,I’vemovedtheArgumentNullExceptionargumentstoseparate
linestofitthebook’slinelength,butthisiswhatyoushouldsee.Next,youcantest
themacrobyrunningit.ClickthelastNameparameterandselectTools|Macros|Run
TemporaryMacroorpressCTRL-SHIFT-P.Thatwillproducethefollowingcode:
publicintAddNewCustomer(stringfirstName,stringlastName)
{
if(string.IsNullOrWhiteSpace(lastName))
{
thrownewArgumentException("lastName","lastNamevalueisnot
valid.");
}
if(string.IsNullOrWhiteSpace(firstName))
{
thrownewArgumentException("firstName","firstNamevalueis
notvalid.");
}
intnewCustID=0;
//Logictoaddcustomer
returnnewCustID;
}
Now,youcanrunthismacroonanyofthestringparametersofmethodsinyour
classandquicklyaddvalidationsupport.Theonlyproblematthepresenttimeisthat
themacroisoverwrittenassoonasyoubeginrecordinganewmacroandthemacrois
goneifyoucloseVS.Thenextsectionaddressesthisproblembyshowingyouhowto
savethemacro.
Saving a Macro
Youcansavemacrostobereusedinlatersessions.Tosavethemacro,selectTools|
Macros|SaveTemporaryMacro.VSwillsaveTemporaryMacroandopentheMacro
Explorerwindow,showninFigure12-8.
VSusesTemporaryMacroasthenameofwhatevermacroitwillrecord.Therefore,
youmustrenamethemacroifyouwanttokeepitbecausethenextrecordingwill
overwritethismacro.RenamethefilemacrotoValidateStringParameterbyright-
clickingTemporaryMacroinMacroExplorer,showingthecontextmenu,andselecting
Rename.
Chapter12: CustomizingtheDevelopmentEnvironment 365
IntheMacroExplorer,youcanaddnewMacroProjects,whicharecontainersfor
holdingmacromodules,byright-clickingMacrosandselectingNewMacroProject.If
someonesharestheirMacroProjectwithyou,right-clickMacrosandselectLoadMacro
Projecttofindtheprojectinthefilesystemandloadit.Macromodulesholdmacros,and
youcanright-clickanymacroproject;suchasMyMacrosorSamplesinFigure12-8,and
selectNewModuletoaddnewmacromodules.Youcanfindallofthesecommandson
theTools|Macrosmenutoo.
Torunanexistingmacro,double-clickthemacroinMacroExplorer.
Tochangeamacro,youcaneitherre-recordoreditanexistingmacro.Thenext
sectionexplainshowtoeditamacro.
Editing Macros
Macrosareeditable,allowingyoutomodifypreviouslyrecordedmacrosorcreatea
brandnewmacro.Toeditamacro,right-clickthemacroinMacroExplorerandselect
Edit.You’llseetheMacroeditor,showninFigure12-9,whichcontainsthecodeforthe
ValidateStringParametermacrocreatedintheprecedingsection.
InFigure12-9,youcanseethattheeditoropensthemacroinacodeeditingwindow.
ThelanguageisVB,soifthelanguageyounormallyprogramwithisC#,youmightwantto
reviewtheVBportionsofChapters2through4asarefresher.ThefeaturesofMacroeditor
areverysimilartothenormalVSIDE,exceptthatnowyoumustworkwithMacroProjects
andModules.Listing12-3showsthemacrocodefromFigure12-9.InListing12-3,boththe
C#andVBmacrosarewritteninVB.However,theC#codeisforamacrothatworksonC#
codeandtheVBcodeisforamacrothatworksonVBcode.
366 MicrosoftVisualStudio2010:ABeginner’sGuide
C#:
OptionStrictOff
OptionExplicitOff
ImportsSystem
ImportsEnvDTE
ImportsEnvDTE80
ImportsEnvDTE90
ImportsEnvDTE90a
ImportsEnvDTE100
ImportsSystem.Diagnostics
PublicModuleRecordingModule
SubValidateStringParameter()
DTE.ActiveDocument.Selection.WordLeft()
DTE.ActiveDocument.Selection.WordRight(True)
DTE.ActiveDocument.Selection.Copy()
DTE.ExecuteCommand("Edit.Find")
Chapter12: CustomizingtheDevelopmentEnvironment 367
DTE.Windows.Item("Customer.cs").Activate()
DTE.Windows.Item("{CF2DDC32-8CAD-11D2-9302-005345000000}")
.Activate()'FindandReplace
DTE.Windows.Item("Customer.cs").Activate()
DTE.Find.FindWhat="{"
DTE.Find.Target=
vsFindTarget.vsFindTargetCurrentDocument
DTE.Find.MatchCase=False
DTE.Find.MatchWholeWord=False
DTE.Find.Backwards=False
DTE.Find.MatchInHiddenText=False
DTE.Find.PatternSyntax=vsFindPatternSyntax
.vsFindPatternSyntaxLiteral
DTE.Find.Action=vsFindAction.vsFindActionFind
If(DTE.Find.Execute()=
vsFindResult.vsFindResultNotFound)Then
ThrowNewSystem.Exception("vsFindResultNotFound")
EndIf
DTE.Windows.Item(
"{CF2DDC32-8CAD-11D2-9302-005345000000}").Close()
DTE.Windows.Item("Customer.cs").Activate()
DTE.ActiveDocument.Selection.EndOfLine()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text="if"
DTE.ExecuteCommand("Edit.InsertTab")
DTE.ExecuteCommand("Edit.InsertTab")
DTE.ActiveDocument.Selection.Text=
"string.IsNullOrWhiteSpace("
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text=")"
DTE.ExecuteCommand("Edit.BreakLine")
DTE.ActiveDocument.Selection.Text=
"thrownewArgumentNullException("""
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text=""","""
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text=
"valueisnotvalid."");"
DTE.ActiveDocument.Selection.LineDown()
DTE.ActiveDocument.Selection.NewLine()
EndSub
EndModule
VB:
OptionStrictOff
OptionExplicitOff
ImportsSystem
ImportsEnvDTE
368 MicrosoftVisualStudio2010:ABeginner’sGuide
ImportsEnvDTE80
ImportsEnvDTE90
ImportsEnvDTE90a
ImportsEnvDTE100
ImportsSystem.Diagnostics
PublicModuleRecordingModule
SubValidateStringParameter()
DTE.ActiveDocument.Selection.WordLeft()
DTE.ActiveDocument.Selection.WordRight(True)
DTE.ActiveDocument.Selection.CharLeft(True)
DTE.ActiveDocument.Selection.Copy()
DTE.ActiveDocument.Selection.EndOfLine()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text="if"
DTE.ExecuteCommand("Edit.InsertTab")
DTE.ExecuteCommand("Edit.InsertTab")
DTE.ActiveDocument.Selection.Text="string.IsNullOrEmpty("
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text=")"
DTE.ActiveDocument.Selection.LineDown()
DTE.ActiveDocument.Selection.Text=
"thrownewArgumentNullException("""
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text=""","""
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text=
"valueisnotvalid."")"
DTE.ActiveDocument.Selection.LineDown()
DTE.ActiveDocument.Selection.NewLine()
EndSub
EndModule
InListing12-3,allofthenamespacesthatbeginwithEnvDTEhavecodethatallows
youtomanipulatetheVSenvironment.ThemacroitselfisaSubwithinaModule.
Eachofthestatementscorrespondstothestepsusedtocreatethemacrointhepreceding
section.Forexample,theFindAndReplacewindowhasseveraloptions,whichthismacro
populates,regardlessofwhethertheycontributetowardthepurposeofthemacro.
Openingamacrointheeditorcanbeveryusefulifyouwanttomakeaquickchange,
withoutneedingtore-recordtheentiremacro.Forexample,whatifyoumissedakeystroke
ormisspelledsomething?Youcanjusteditthecode,savethefile,closetheMacroeditor,
andthenre-runthemacro.Infact,thereisaproblemwiththemacroforC#;itwillonly
Chapter12: CustomizingtheDevelopmentEnvironment 369
workonthefileyouranitin.Thisproblemdoesn’toccurinthemacroforVB.I’llshow
youhowtofixthisproblem,butlet’sopenthemacroeditorfirst.
YoucanopentheMacroeditorthroughVSbyselectingTools|Macros|MacrosIDE,
startanewproject,addamoduletotheproject,andaddaSubtotheModuleasanew
macro.ThencodethemacrobytypingDTE.andusingIntellisensetofindvariousparts
oftheIDE.ThecrypticparametertoWindows.Item,{CF2DDC32-8CAD-11D2-9302-
005345000000},fortheFindAndReplacewindowiscalledaGloballyUniqueIdentifier
(GUID).AGUIDisoftenusedasaspecialidentifierforsoftwarecomponentsandisthe
methodusedinVStouniquelyidentifytools.So,DTE.Windows.Item("{CF2DDC32-
8CAD-11D2-9302-005345000000}").Activate()isawaytoreferenceandopentheFind
AndReplacewindow.
ThereisaproblemwiththemacroforC#inListing12-3,becauseitwillonlyworkin
theCustomer.csfileinVS.TheVBcodebelowisprovidedforyourconvenience,butthis
problemonlyoccurswiththemacrowrittenforC#code;theVBmacroworksfineonthe
VBcodebelow.IfyoucreatedanewclassnamedProductinafilenamedProduct.csand
addedanAddNewProductmethodlikethefollowing,themacrowilltrytoopenandwrite
intotheCustomer.csfile,whichisnottheresultyouwant:
C#:
usingSystem;
namespaceConsoleApplication1
{
classProduct
{
publicintAddNewProduct(stringproductName)
{
intnewProdID=0;
//Logictoaddproduct
returnnewProdID;
}
}
}
VB(doesn’thaveproblemthatoccursinC#code):
PublicClassProduct
FunctionAddNewProduct(ByValproductNameAsString)AsInteger
DimnewProdIDAsInteger=0
370 MicrosoftVisualStudio2010:ABeginner’sGuide
'Logictoaddproduct
ReturnnewProdID
EndFunction
EndClass
Tofixtheproblemwiththemacro(fortheC#code)openingtheCustomer.csfile,
noticethatthemacrohasthreestatementsthatactivatetheCustomer.csfile.Commentout
eachofthesestatementsasshowninthefollowingexcerpt:
…
'DTE.Windows.Item("Customer.cs").Activate()
…
'DTE.Windows.Item("Customer.cs").Activate()
DTE.Find.FindWhat="{"
…
'DTE.Windows.Item("Customer.cs").Activate()
…
Ifyouweretowriteyourownmacroviacode,aquickwaytofigureoutwhatcode
youhavetowriteistostartthemacrorecorderinVS(CTRL-SHIFT-R),usetheVSfeature
youwanttocode,stoprecording(CTRL-SHIFT-R),andsavethemacro.Theninspectthecode
intheMacroeditorandcopythepartsyouneed.Thistechniqueisespeciallyvaluableto
figureouthowtoopenwindows,suchastheFindAndReplacewindowdiscussedinthe
precedingparagraph.Forevenmorehelp,thereareseveralexamplemacrosunderthe
Samplesfolder,showninFigure12-9,showingyoudifferentwaystowriteVSmacros.
Summary
NowyouknowaboutvarioustechniquesforcustomizingVS.Youlearnedhowtocustomize
projectsandsaveyourworkasacustomprojecttemplate.Inarelatedtask,yousawhow
youcancreateanewfileandthensavethatfileasacustomitemtemplate.Thisgivesyou
theabilitytouseprojectsandprojectitemsinawaythatyouwant.Inadditiontousing
snippetsthatshipwithVS,youlearnedhowtofindthedefinitionofexistingsnippetsand
eithermodifyasnippetorcreateabrandnewsnippetfromscratch.Youalsosawhowto
organizesnippetswiththeSnippetsManager.Finally,youlearnedhowtorecordandsave
repeatableactionswithVSmacros.YoucanalsousetheMacroeditortocustomizeexisting
macrosorcreatenewonesonyourown.
Macrosareverypowerful,butVShasevenmorecapabilitiesforallowingyouto
extendtheIDE.You’lllearnhowtoextendVSbywritingAdd-Insinthenextchapter.
Chapter 13
Extending Visual
Studio 2010
371
372 MicrosoftVisualStudio2010:ABeginner’sGuide
KeySkills&Concepts
● CreateanAdd-InwithVS
● LearnWhatTypesofAdd-InstoCreate
● DeployanAdd-In
P reviouschaptersdiscussedmanywaystouseVS,andtheprecedingchaptershowed
youafewwaystocreateyourowncustomizations.Inparticular,macrosofferthe
abilitytoperformrepeatableactionsandgiveyouaccesstomuchofwhatVShastooffer.
Takingcustomizationonestepbeyondmacros,thischaptershowsyouhowtoextendVS
functionalitywithasoftwarecomponentcalledanAdd-In.
Essentially,anAdd-Inisasoftwarecomponentthatallowsyoutoaddnewcapabilities
toVSthathaven’texistedbefore.TheAdd-InplugsintoVS,andyoucanrunitasifit
werepartofVS.ThischaptershowsyouhowtheprocessofcreatinganAdd-Inworks.
You’llseehowtoaddfunctionalitytomakeanAdd-Inperformanytaskyouwant.Besides
creatinganAdd-In,thischapterpointsyouintherightdirectionsothatyoucanfigureout
howtoaccessthedifferentpartsofVS.ThespecificexampleinthischapterisanAdd-
InthatfindsalloftheshortcutkeysinVSandprintsthemtotheOutputwindow.With
knowledgeofhowtocreateanAdd-In,you’lllearnhowtodeploytheAdd-Insothatitcan
beloadedintoVS.We’llbeginwithawalk-throughofhowVShelpsyoucreateanAdd-In.
1.OpenVSandpressCTRL-SHIFT-NtoopentheNewProjectwindow.SelectOtherProject
Types|ExtensibilityandobservethattherearetwotypesofAdd-Inprojecttypes:
VisualStudioAdd-InandSharedAdd-In.TheSharedAdd-Iniswhatyouwoulduse
tocreateaMicrosoftOfficeAdd-In.TheVisualStudioAdd-Inisappropriatelynamed
becauseitdescribeswhatwewanttodo.Figure13-1showswhatthescreenshould
looklike.
2.SelectVisualStudioAdd-In.NametheprojectKeystrokeFinder,specifythelocation
whereyouwanttheprojecttobe,andclickOK.ClickNexttopasstheWelcomescreen
andyou’llseetheSelectAProgrammingLanguagescreen,showninFigure13-2.
3.Pickthelanguageyouwouldliketouse.Thisbookdoesn’tdiscussC++,butitwould
besafetopickeitherC#orVB,whichyoucanlearnmoreaboutinChapters2through4.
ClickNexttorevealtheSelectAnApplicationHostwindow,showninFigure13-3.
4.YourchoicesincludeMicrosoftVisualStudio2010andMicrosoftVisualStudio2010
Macros.CheckingMicrosoftVisualStudio2010willallowtheAdd-Intoworkinthe
VSenvironment,whichyou’veusedformostofthisbook.CheckingMicrosoftVisual
374 MicrosoftVisualStudio2010:ABeginner’sGuide
Studio2010MacroswillallowthisAdd-IntoworkwiththeMacroEditor,explained
intheprecedingchapter.We’reonlyinterestedinVSforthecurrentAdd-In,socheck
onlyMicrosoftVisualStudio2010(nottheMacrosoption).ClickNexttodisplaythe
EnterANameAndDescriptionwindow,showninFigure13-4.
5.TheEnterANameAndDescriptionwindowstartsbyappending“–NoNameprovided.”
and“–NoDescriptionprovided.”tothenameoftheprojectinthenameanddescription
fields,respectively.Justdeletethedefaultsandaddthenameanddescriptionyouwant
theAdd-Intohave.TheAdd-Inwillbenamedafterwhatyouputhere,anduserswill
beabletoreadthedescriptionintheVSAdd-InManager,whichI’lldiscusslaterinthis
chapter.ClickNexttodisplaytheChooseAdd-InOptionswindow,showninFigure13-5.
6.ThefirstchoiceinFigure13-5,“WouldyouliketocreatecommandbarUIforyour
Add-In?”willaddamenuitemtotheToolsmenuwiththenameofyourAdd-In.
Checkthesecondboxtoo,allowingtheAdd-IntoloadwhenVSloads;thealternative
beingthatyoucanmanuallyloadtheAdd-InviatheAdd-InManager,discussedlater
inthischapter.ThethirdoptioncomesintoplaywhenyouwanttoallowtheAdd-In
toworkwhensomeonerunsVSviathecommandline.Theprecedingchaptershows
anexampleofrunningVSonthecommandlinewheninstallingtheglobalproject
templatesbyrunningdevenv/installvstemplates.Poppingupamodalwindow(one
thatrequiresyoutoclickanOKbuttontomakeitgoaway)willstopacommand-line
operationfromrunningbecauseitisexpectingacknowledgmentofthemodalwindow.
Ifthatcommand-lineoperationwererunningasascheduledWindowsbackgroundjob,
therewouldbenowaytoacknowledgethewindowandthejobwouldnotwork.So,
checkthethirdboxonlyifit’ssafetorunviathecommandline.Checkthefirsttwo
boxesandleavethethirdboxunchecked.ClickNexttomovetotheChoosing‘Help
About’Informationwindow,showninFigure13-6.
7.YoucanoptionallyshowanAboutwindowforyourAdd-In.Checktheboxandmodify
thetextthatyouwouldliketoshowintheAboutbox.ClickNextandclickFinishon
theSummarywindow.
AfteraminuteVSwillcreateanewsolutionandprojectthatcontainsitemsthathelp
youcreateanAdd-In.Thenextsectiondiscusseswhatthoseprojectitemsare.
methodsthatarenumbered,suchastheIDTExtensibilityandIDTExtensibility2,where
IDTExtensibility2isamorerecentversionwithadditionalmembers.I’llexplainwhatthe
IDTExtensibility2interfacedoeslater,butwhatyoushouldgetoutofthisexampleishow
eachversionoftheEnvDTEassembliesmanagesnewerversionsofcode.Thisscheme
promotestheadditionofnewfunctionalityforeachversionofVSwithoutsacrificing
backwardcompatibility.
TheConnectclasscontainsthecodethatinteractswithVStomakeanAdd-Inwork.
Remember,thisisaVSproject,justlikealloftheotherprojectsyoucancreate.You’re
freetoaddclassescontainingyourfunctionalityandhavecodeinConnectcallyour
classes,organizecodeintofolders,oraddaclasslibrarytothesolutionandcallcodein
theclasslibrary.ThenextsectiondiscussesinternalsofConnectindetail.
Theotheritemsofnoteinthisprojectarethefileswiththe*.AddInextensions.
Thesearethedeploymentfiles.Therewasatimewhenyouwererequiredtogointothe
WindowsregistrytoconfigureanAdd-In,butnotanymore.TheAdd-Inconfigurationis
doneinthe*.AddInfiles,whichcontainsXML.Inalatersectionofthischapter,you’ll
seetheinternalsofthe*.AddInfileandlearnhowtomanipulatethisfilefordeployment.
Additionally,oneofthe*.AddInfileshasashortcutarrow,whichisaspecialshortcut
toafileusedfordebugging.Ifyoulookatthepropertiesforthisshortcutfile,you’ll
noticethatitpointsatyourDocuments\VisualStudio2010\Addins\folder,whichisa
deploymentlocation.Wheneveryoudebugthisapplication,VSusesthedebugging
*.AddInfiletoloadtheAdd-IninanewcopyofVS.YouwouldmanipulatetheAdd-Inin
thenewcopyofVS,andyourcurrentcopyofVS,indebuggingmode,canhitbreakpoints
anddebugtheAdd-In.
NowthatyouknowthekeyelementsofanAdd-Inproject,thenextsectiondrillsdown
intotheConnectclassanddescribesthemembersthatinteractwithVStorunanAdd-In.
Member Purpose
OnAddInsUpdate Add-In is either loaded or unloaded.
OnBeginShutdown Add-In is running and VS shuts down.
OnConnection Add-In is loaded.
OnDisconnection Add-In is unloaded.
OnStartupComplete VS has started up and then Add-In is loaded.
It’slikepeoplefromdifferentcountriestryingtocommunicate,wheretheyhaveasubject
todiscussbutneedacommonlanguagetobeabletounderstandeachother;thecommon
languagewouldbetheinterfacebetweenthepeople.
ThefirstinterfacetodiscussisIDTExtensibility2,whosepurposeistoletVSmanage
loadingandunloadingoftheAdd-In.LoadingandunloadingareimportantbecauseVS
loadsAdd-InswhenitstartsandunloadsAdd-Inswhenitshutsdown.Therearecertain
actionsthatyoumightwanttotake,dependingonwhentheAdd-Inisloadedandwhat
typeofinformationyoumightneedaccessto.Forexample,theveryfirsttimeanAdd-In
iseverloaded,youmightwanttoperformaspecialoperationlikeconfigurationorasking
theuserifshewouldliketoregisteryourAdd-In.Table13-1showsthemembersof
IDTExtensibility2anddescribestheirpurpose.
ThesecondinterfacethatConnectimplementsisIDTCommandTarget.Whenbuildingan
Add-In,youneedawayfortheVSIDEtoexecutetheAdd-In.Forexample,youwillcreate
anamedcommandthatexposestheAdd-InasamenuitemintheToolsmenu.Whenever
auserselectsthemenuitem,thenamedcommandwillexecuteandrunyourAdd-Incode.
IDTCommandTargetistheinterfaceVSusestoexecuteyourAdd-In.Table13-2showsthe
membersofIDTCommandTargetanddescribestheirpurpose.
EachofthemethodsofboththeIDTExtensibility2andIDCommandTargetinterfacesare
implementedbytheprovidedConnectclass.Listing13-1showseachofthesememberswith
fulldocumentationcommentsandskeletoncode.ThecodeinListing13-1isinC#,butitis
veryinformativetotaketheoverviewoftheinterfacesfromtheprevioustableandthen
Member Purpose
Exec Called by VS to execute your Add-In.
QueryStatus Called by VS to determine if the command should be enabled,
invisible, or supported.
takeanevencloserlookatthecommentsinthecodeforabetterunderstandingofwhat
thatcodedoes.ThecodecommentsareexactlythesameinVB.Someofthecomments
refertothehostapplication,wherethehostiseithertheVSIDEortheVSMacroEditor,as
wasselectedwhilerunningtheAdd-InProjectWizardintheprecedingsectionandshown
inFigure13-3.I’veremovedthecontentsofeachmethodbecausesubsequentsectionsof
thischapterwillexplainimportantmethodimplementationsandhowtomaketheAdd-In
performusefuloperations.
usingSystem;
usingExtensibility;
usingEnvDTE;
usingEnvDTE80;
usingMicrosoft.VisualStudio.CommandBars;
usingSystem.Resources;
usingSystem.Reflection;
usingSystem.Globalization;
namespaceKeystrokeFinder
{
///<summary>TheobjectforimplementinganAdd-in.</summary>
///<seealsoclass='IDTExtensibility2'/>
publicclassConnect:IDTExtensibility2,IDTCommandTarget
{
///<summary>
///ImplementstheconstructorfortheAdd-inobject.
///Placeyourinitializationcodewithinthismethod.
///</summary>
publicConnect()
{
}
///<summary>
///ImplementstheOnConnectionmethodofthe
///IDTExtensibility2interface.Receivesnotification
///thattheAdd-inisbeingloaded.
///</summary>
///<paramterm='application'>
///Rootobjectofthehostapplication.
///</param>
///<paramterm='connectMode'>
///DescribeshowtheAdd-inisbeingloaded.
///</param>
Chapter13: ExtendingVisualStudio2010 381
///<paramterm='addInInst'>
///ObjectrepresentingthisAdd-in.
///</param>
///<seealsoclass='IDTExtensibility2'/>
publicvoidOnConnection(
objectapplication,ext_ConnectModeconnectMode,
objectaddInInst,refArraycustom)
{
}
///<summary>
///ImplementstheOnDisconnectionmethodofthe
///IDTExtensibility2interface.Receivesnotification
///thattheAdd-inisbeingunloaded.
///</summary>
///<paramterm='disconnectMode'>
///DescribeshowtheAdd-inisbeingunloaded.
///</param>
///<paramterm='custom'>
///Arrayofparametersthatarehostapplicationspecific.
///</param>
///<seealsoclass='IDTExtensibility2'/>
publicvoidOnDisconnection(
ext_DisconnectModedisconnectMode,refArraycustom)
{
}
///<summary>
///ImplementstheOnAddInsUpdatemethodofthe
///IDTExtensibility2interface.Receivesnotification
///whenthecollectionofAdd-inshaschanged.
///</summary>
///<paramterm='custom'>
///Arrayofparametersthatarehostapplicationspecific.
///</param>
///<seealsoclass='IDTExtensibility2'/>
publicvoidOnAddInsUpdate(refArraycustom)
{
}
///<summary>
///ImplementstheOnStartupCompletemethodofthe
///IDTExtensibility2interface.Receivesnotification
///thatthehostapplicationhascompletedloading.
///</summary>
///<paramterm='custom'>
382 MicrosoftVisualStudio2010:ABeginner’sGuide
///Arrayofparametersthatarehostapplicationspecific.
///</param>
///<seealsoclass='IDTExtensibility2'/>
publicvoidOnStartupComplete(refArraycustom)
{
}
///<summary>
///ImplementstheOnBeginShutdownmethodofthe
///IDTExtensibility2interface.Receivesnotification
///thatthehostapplicationisbeingunloaded.
///</summary>
///<paramterm='custom'>
///Arrayofparametersthatarehostapplicationspecific.
///</param>
///<seealsoclass='IDTExtensibility2'/>
publicvoidOnBeginShutdown(refArraycustom)
{
}
///<summary>
///ImplementstheQueryStatusmethodofthe
///IDTCommandTargetinterface.Thisiscalled
///whenthecommand'savailabilityisupdated
///</summary>
///<paramterm='commandName'>
///Thenameofthecommandtodeterminestatefor.
///</param>
///<paramterm='neededText'>
///Textthatisneededforthecommand.
///</param>
///<paramterm='status'>
///Thestateofthecommandintheuserinterface.
///</param>
///<paramterm='commandText'>
///TextrequestedbytheneededTextparameter.
///</param>
///<seealsoclass='Exec'/>
publicvoidQueryStatus(
stringcommandName,
vsCommandStatusTextWantedneededText,
refvsCommandStatusstatus,
refobjectcommandText)
{
}
Chapter13: ExtendingVisualStudio2010 383
///<summary>
///ImplementstheExecmethodoftheIDTCommandTarget
///interface.Thisiscalledwhenthecommandisinvoked.
///</summary>
///<paramterm='commandName'>
///Thenameofthecommandtoexecute.
///</param>
///<paramterm='executeOption'>
///Describeshowthecommandshouldberun.
///</param>
///<paramterm='varIn'>
///Parameterspassedfromthecallertothecommandhandler.
///</param>
///<paramterm='varOut'>
///Parameterspassedfromthecommandhandlertothecaller.
///</param>
///<paramterm='handled'>
///Informsthecallerifthecommandwashandledornot.
///</param>
///<seealsoclass='Exec'/>
publicvoidExec(
stringcommandName,vsCommandExecOptionexecuteOption,
refobjectvarIn,refobjectvarOut,refboolhandled)
{
}
privateDTE2_applicationObject;
privateAddIn_addInInstance;
}
}
You’vehadanoverviewofwhattheIDTExtensibility2andIDTCommandTarget
interfacesdoandreviewedthecommentsinListing13-1.Inthenextsection,you’llsee
howtoaddyourowncodetotheinterfacemethodstomaketheKeystrokeFinderAdd-In
performsomeusefulwork.
C#:
publicvoidOnConnection(
objectapplication,ext_ConnectModeconnectMode,
objectaddInInst,refArraycustom)
{
_applicationObject=(DTE2)application;
_addInInstance=(AddIn)addInInst;
if(connectMode==ext_ConnectMode.ext_cm_UISetup)
{
object[]contextGUIDS=newobject[]{};
Commands2commands=
(Commands2)_applicationObject.Commands;
stringtoolsMenuName="Tools";
Microsoft.VisualStudio.CommandBars.CommandBar
menuBarCommandBar=((
Microsoft.VisualStudio.CommandBars.CommandBars)
_applicationObject.CommandBars)["MenuBar"];
CommandBarControltoolsControl=
menuBarCommandBar.Controls[toolsMenuName];
CommandBarPopuptoolsPopup=
(CommandBarPopup)toolsControl;
try
{
Commandcommand=commands.AddNamedCommand2(
_addInInstance,"KeystrokeFinder",
"KeystrokeFinder",
"ExecutesthecommandforKeystrokeFinder",
true,59,refcontextGUIDS,
(int)vsCommandStatus
.vsCommandStatusSupported+
(int)vsCommandStatus.vsCommandStatusEnabled,
386 MicrosoftVisualStudio2010:ABeginner’sGuide
(int)vsCommandStyle
.vsCommandStylePictAndText,
vsCommandControlType
.vsCommandControlTypeButton);
if((command!=null)&&
(toolsPopup!=null))
{
command.AddControl(
toolsPopup.CommandBar,1);
}
}
catch(System.ArgumentException)
{
}
}
}
VB:
PublicSubOnConnection(
ByValapplicationAsObject,
ByValconnectModeAsext_ConnectMode,
ByValaddInInstAsObject,
ByRefcustomAsArray)ImplementsIDTExtensibility2.OnConnection
_applicationObject=CType(application,DTE2)
_addInInstance=CType(addInInst,AddIn)
IfconnectMode=ext_ConnectMode.ext_cm_UISetupThen
DimcommandsAsCommands2=
CType(_applicationObject.Commands,Commands2)
DimtoolsMenuNameAsString="Tools"
DimcommandBarsAsCommandBars=
CType(_applicationObject.CommandBars,CommandBars)
DimmenuBarCommandBarAsCommandBar=
commandBars.Item("MenuBar")
DimtoolsControlAsCommandBarControl=
menuBarCommandBar.Controls.Item(toolsMenuName)
DimtoolsPopupAsCommandBarPopup=
CType(toolsControl,CommandBarPopup)
Try
Chapter13: ExtendingVisualStudio2010 387
DimcommandAsCommand=
commands.AddNamedCommand2(
_addInInstance,"KeystrokeFinderVB",
"KeystrokeFinderVB",
"ExecutesthecommandforKeystrokeFinderVB",
True,59,Nothing,
CType(vsCommandStatus.vsCommandStatusSupported,
Integer)+
CType(vsCommandStatus.vsCommandStatusEnabled,
Integer),
vsCommandStyle.vsCommandStylePictAndText,
vsCommandControlType.vsCommandControlTypeButton)
command.AddControl(toolsPopup.CommandBar,1)
CatchargumentExceptionAsSystem.ArgumentException
EndTry
EndIf
EndSub
DissectingListing13-2intoitsconstituentpartsdemonstratestheroleOnConnection
hasandhowitaffectssubsequentcode.Thefirstpartofthemethodobtainsreferencestoa
coupleofimportantobjects:applicationandaddInInst.Thefollowingexcerptshowshow
toobtainareferencetotheseobjectsandconvertthemtoDTE2andAddIn,respectively.
Thereferencesto_applicationObjectand_addInInstancearefieldsoftheConnectclass,
whichisimportantbecausenowothermethodsoftheclasswillbeabletoaccessthese
objects.
C#:
_applicationObject=(DTE2)application;
_addInInstance=(AddIn)addInInst;
VB:
_applicationObject=CType(application,DTE2)
_addInInstance=CType(addInInst,AddIn)
TheremainingcodeinOnConnectionsetsupthemenuitemundertheToolsmenu,
asdirectedbychoosingtobuildacommandUI,showninFigure13-5.However,this
onlyoccursonetime—thefirsttimetheapplicationruns.Tomakesurethemenuitem
setsuponetime,thecodecheckstheconnectModeparametertoseeifit’ssetto
388 MicrosoftVisualStudio2010:ABeginner’sGuide
ext_ConnectMode.ext_cm_UISetup,asshowninthefollowingcode.Theremaining
codeintheOnConnectionmethodwillonlyexecuteifthefollowingconditionistrue:
C#:
if(connectMode==ext_ConnectMode.ext_cm_UISetup)
VB:
IfconnectMode=ext_ConnectMode.ext_cm_UISetupThen
Thefirsttimethecoderuns,thecodewithintheprecedingifstatementwillexecute,
creatingamenuitemfortheKeystrokeFinderAdd-InintheToolsmenu.Codeexamples
thatfollowinthissectionareallcontainedwithintheprecedingifstatement;thisisgood
informationtoknowbecauseitshowsyouhowtonavigatetheVSobjectmodeltofind
something.
Thefollowingcodeuses_applicationObjecttogetalistofcommands,whichisalist
ofalltheactionsyoucantakewithVS.Asdiscussedearlier,_applicationObjectistype
DTE2andservesastheparentobjectforaccessingallfunctionalityinVS.
C#:
Commands2commands=
(Commands2)_applicationObject.Commands;
VB:
DimcommandsAsCommands2=
CType(_applicationObject.Commands,Commands2)
IntheVSautomationobjectmodel,amenuitemiscalledaCommandBar.So,youget
areferencetoaCommandBarscollection,againthrough_applicationObject,toreference
theMenuBar,whichisthemainVSmenu,assignedtomenuBarCommandBar:
C#:
Microsoft.VisualStudio.CommandBars.CommandBar
menuBarCommandBar=((
Microsoft.VisualStudio.CommandBars.CommandBars)
_applicationObject.CommandBars)["MenuBar"];
VB:
DimcommandBarsAsCommandBars=
CType(_applicationObject.CommandBars,CommandBars)
DimmenuBarCommandBarAsCommandBar=
commandBars.Item("MenuBar")
Chapter13: ExtendingVisualStudio2010 389
WithintheCommandBarscollection,menuBarCommandBar,youthenlookintothe
Controlscollection,whichisalistofmenusonthemainmenutofindtheToolsmenu,
assignedtotoolsControlasfollows:
C#:
stringtoolsMenuName="Tools";
CommandBarControltoolsControl=
menuBarCommandBar.Controls[toolsMenuName];
VB:
DimtoolsMenuNameAsString="Tools"
DimtoolsControlAsCommandBarControl=
menuBarCommandBar.Controls.Item(toolsMenuName)
IntheVSautomationobjectmodel,anindividualmenuisaCommandBarPopup,
assignedtotoolsPopupasfollows:
C#:
CommandBarPopuptoolsPopup=
(CommandBarPopup)toolsControl;
VB:
DimtoolsPopupAsCommandBarPopup=
CType(toolsControl,CommandBarPopup)
NowyouhaveareferencetothemenuwherethemenuitemfortheAdd-Inmust
beadded.Youarereadytoaddthecommand,usingtheAddNamedCommand2method
ofthecommandscollection.Rememberthatearliercodeassignedthesecommands
fromtheapplicationobjecttothecommandsvariable.Aquickreviewofthearguments
toAddNamedCommand2givesyouthegistofwhat’shappening:Thecodepassesa
referencetotheAdd-In;providesamenuitemnameanddescription;andindicatesthat
thestatusofthecommandissupportedandenabled,themenuitemwillhavepicturesand
text,andthetypeofmenuitemisbutton(canbeclicked).Ifyouwantallthedetailsof
thismethodcall,nowisagoodtimetorefertothedocumentation.Whileit’simportantto
understandthemajorinterfaces,suchasOnConnectionforIDTExtensibility2,memorizing
everyAPIcallmightnotbethemostproductiveuseofyourtimewhenyou’rejuststarting
out.ThefollowingcodeshowsthecalltoAddNamedCommand2:
C#:
Commandcommand=commands.AddNamedCommand2(
_addInInstance,"KeystrokeFinder",
"KeystrokeFinder",
"ExecutesthecommandforKeystrokeFinder",
390 MicrosoftVisualStudio2010:ABeginner’sGuide
true,59,refcontextGUIDS,
(int)vsCommandStatus
.vsCommandStatusSupported+
(int)vsCommandStatus.vsCommandStatusEnabled,
(int)vsCommandStyle
.vsCommandStylePictAndText,
vsCommandControlType
.vsCommandControlTypeButton);
VB:
DimcommandAsCommand=
commands.AddNamedCommand2(
_addInInstance,"KeystrokeFinderVB",
"KeystrokeFinderVB",
"ExecutesthecommandforKeystrokeFinderVB",
True,59,Nothing,
CType(vsCommandStatus.vsCommandStatusSupported,
Integer)+
CType(vsCommandStatus.vsCommandStatusEnabled,
Integer),
vsCommandStyle.vsCommandStylePictAndText,
vsCommandControlType.vsCommandControlTypeButton)
AddNamedCommand2returnedaCommandobject,command,whichmustbeplaced
intoVSsomewheresothatausercanclickittoinvoketheAdd-In.Thenextstatement
accomplishesthistaskbyaddingcommandtotheToolsmenu.Asyoumayrecallfrom
previousexamples,thecodesearchedforandobtainedareferencetotheToolsmenu.After
ensuringthatboththecommandandtoolsPopuprefertovalidobjects(abestpractice),the
followingcodeplacescommandintothefirstposition(atthetop)oftheToolsmenu:
C#:
if((command!=null)&&
(toolsPopup!=null))
{
command.AddControl(
toolsPopup.CommandBar,1);
}
VB:
command.AddControl(toolsPopup.CommandBar,1)
ThiscompletestheresponsibilitiesoftheOnConnectionmethod.Ifyouhadyourown
codeforinitializingtheAdd-In,theOnConnectionmethodwouldbeagoodplacetoput
it.TheprecedingexamplewasusefulbecausenowyouknowhowtoaccessVSmenus
andcommands.Theexamplealsodemonstratedtheimportanceofthemainapplication
objectandhowit’susedasthestartingpointforgettingtootherpartofVS.
Chapter13: ExtendingVisualStudio2010 391
Asyoumayrecall,theOnConnectionmethodassignedthemainapplicationobjectto
_applicationObject,afieldoftheConnectclass.Thisisimportantbecausenowyouhave
accesstothemainapplicationobject,andyou’llseehowit’susedinthenextsection,
whichshowsyouhowtoexecuteyourAdd-InviatheExecmethod.
C#:
publicvoidExec(
stringcommandName,vsCommandExecOptionexecuteOption,
refobjectvarIn,refobjectvarOut,refboolhandled)
{
handled=false;
if(executeOption==
vsCommandExecOption.vsCommandExecOptionDoDefault)
{
if(commandName==
"KeystrokeFinder.Connect.KeystrokeFinder")
{
OutputWindowoutWin=
_applicationObject.ToolWindows.OutputWindow;
OutputWindowPaneoutPane=
outWin.OutputWindowPanes.Add(
"KeyboardShortcuts");
outPane.Activate();
foreach(Commandcmdin
_applicationObject.Commands)
{
object[]cmdBindings=
cmd.Bindingsasobject[];
392 MicrosoftVisualStudio2010:ABeginner’sGuide
if(cmdBindings.Length>0)
{
stringbindingStr=
string.Join(",",cmdBindings);
outPane.OutputString(
"Command:"+cmd.Name+
",Shortcut:"+bindingStr+
"\n");
}
}
handled=true;
return;
}
}
}
VB:
PublicSubExec(
ByValcommandNameAsString,
ByValexecuteOptionAsvsCommandExecOption,
ByRefvarInAsObject,ByRefvarOutAsObject,
ByRefhandledAsBoolean)ImplementsIDTCommandTarget.Exec
handled=False
IfexecuteOption=
vsCommandExecOption.vsCommandExecOptionDoDefaultThen
IfcommandName=
"KeystrokeFinderVB.Connect.KeystrokeFinderVB"Then
DimoutWinAsOutputWindow=
_applicationObject.ToolWindows.OutputWindow
DimoutPaneAsOutputWindowPane=
outWin.OutputWindowPanes.Add(
"KeyboardShortcuts")
outPane.Activate()
ForEachcmdAsCommandIn_applicationObject.Commands
DimcmdBindingsAsObject()=
CType(cmd.Bindings,Object())
IfcmdBindings.Length>0Then
DimbindingStrAsString=
String.Join(",",cmdBindings)
Chapter13: ExtendingVisualStudio2010 393
outPane.OutputString(
"Command:"&cmd.Name&
",Shortcut:"&bindingStr&
Environment.NewLine)
EndIf
Next
handled=True
ExitSub
EndIf
EndIf
EndSub
TheexecuteOptionparameterofExecallowsyoutodeterminewhetheryouwant
toprompttheuserforinput,performtheaction,orshowhelp,whichareoptionsofthe
vsCommandExecOption.Allyouneedtodoischecktheoptionandperformtheoperationfor
thecurrentvalueofexecuteOption.InthecurrentAdd-In,weonlycheckforvsCommandExec
OptionDoDefault,whichmeanstojustperformtheoperation:
C#:
if(executeOption==
vsCommandExecOption.vsCommandExecOptionDoDefault)
VB:
IfexecuteOption=
vsCommandExecOption.vsCommandExecOptionDoDefaultThen
Theexampleinthischapteronlyhasonecommand,butyoucouldpotentiallyhave
multiplecommandsifyoudecidedtoaddmorecommandsintheOnConnectionmethod.
Addanifstatementtoensureyou’reexecutingcodeforthepropercommand,suchasthe
followingcode:
C#:
if(commandName==
"KeystrokeFinder.Connect.KeystrokeFinder")
VB:
IfcommandName=
"KeystrokeFinderVB.Connect.KeystrokeFinderVB"Then
394 MicrosoftVisualStudio2010:ABeginner’sGuide
Asyoulearnedearlier,theapplicationobjectisthestartingpointforaccessingallVS
objects.SinceweneedtowritetotheOutputwindow,thecodeaccessestheToolWindows
propertyoftheapplicationobject,whichprovidesaccesstomultipleVSwindows.The
followingcodeobtainsareferencetotheOutputWindow,addsanewpane,andactivates
thepane:
C#:
OutputWindowoutWin=
_applicationObject.ToolWindows.OutputWindow;
OutputWindowPaneoutPane=
outWin.OutputWindowPanes.Add(
"KeyboardShortcuts");
outPane.Activate();
VB:
DimoutWinAsOutputWindow=
_applicationObject.ToolWindows.OutputWindow
DimoutPaneAsOutputWindowPane=
outWin.OutputWindowPanes.Add(
"KeyboardShortcuts")
outPane.Activate()
Goingbacktotheapplicationobject,weneedtoaccesstheCommandscollection,usinga
foreachlooptoaccesseachCommandobject.EachcommandnameisintheNameproperty.
TheBindingspropertyisacollectionofshortcutkeysforthecommand.Somecommandshave
noshortcutkeys,asindicatedbyanemptyBindingscollection(itsLengthpropertywillbeset
to0),soweskipthem.ThefollowingcodeshowshowtoiteratethroughallVScommandsand
printeachcommandnameandassociatedshortcutkeystotheOutputwindow:
C#:
foreach(Commandcmdin
_applicationObject.Commands)
{
object[]cmdBindings=
cmd.Bindingsasobject[];
if(cmdBindings.Length>0)
{
stringbindingStr=
string.Join(",",cmdBindings);
outPane.OutputString(
"Command:"+cmd.Name+
Chapter13: ExtendingVisualStudio2010 395
",Shortcut:"+bindingStr+
"\n");
}
}
handled=true;
VB:
ForEachcmdAsCommandIn_applicationObject.Commands
DimcmdBindingsAsObject()=
CType(cmd.Bindings,Object())
IfcmdBindings.Length>0Then
DimbindingStrAsString=
String.Join(",",cmdBindings)
outPane.OutputString(
"Command:"&cmd.Name&
",Shortcut:"&bindingStr&
Environment.NewLine)
EndIf
Next
handled=True
Noticehowwesethandledtotrue,lettingVSknowthatthecoderecognizedand
actedonthecommand.BesideslettingusersexecutetheAdd-In,youwanttoensuretheir
experiencewiththeAdd-Inislogicalandthecommanddisplaysitsstatusproperly,as
you’lllearnaboutinthenextsection.
C#:
publicvoidQueryStatus(
stringcommandName,
396 MicrosoftVisualStudio2010:ABeginner’sGuide
vsCommandStatusTextWantedneededText,
refvsCommandStatusstatus,
refobjectcommandText)
{
if(neededText==
vsCommandStatusTextWanted
.vsCommandStatusTextWantedNone)
{
if(commandName==
"KeystrokeFinder.Connect.KeystrokeFinder")
{
status=
(vsCommandStatus)
vsCommandStatus.vsCommandStatusSupported|
vsCommandStatus.vsCommandStatusEnabled;
return;
}
}
}
VB:
PublicSubQueryStatus(
ByValcommandNameAsString,
ByValneededTextAsvsCommandStatusTextWanted,
ByRefstatusAsvsCommandStatus,
ByRefcommandTextAsObject)ImplementsIDTCommandTarget.
QueryStatus
IfneededText=
vsCommandStatusTextWanted.vsCommandStatusTextWantedNoneThen
IfcommandName=
"KeystrokeFinderVB.Connect.KeystrokeFinderVB"Then
status=
CType(vsCommandStatus.vsCommandStatusEnabled+
vsCommandStatus.vsCommandStatusSupported,
vsCommandStatus)
Else
status=vsCommandStatus.vsCommandStatusUnsupported
EndIf
EndIf
EndSub
Chapter13: ExtendingVisualStudio2010 397
TheQueryStatusmethodinListing13-4checksthecommandNametoensureit’s
workingwiththerightAdd-In.Ifso,itsetsthestatusparametertoacombinationofvalues
fromthevsCommandStatusenum.InListing13-4,thestatusissupportedandenabled.
ThisdemonstratedhowtocreateanAdd-In.Next,you’lllearnhowtodeploytheAdd-In.
Deploying an Add-In
TherearetwofilesinvolvedindeployingyourAdd-In:a*.AddInfileand*.dll.The
*.AddInfilecontainsregistrationinformationforyourAdd-In,and*.dllistheclass
libraryoutputassemblythatcontainsyourAdd-In.
Youcandeploythe*.AddInfilebycopyingitintoafolderthatVSrecognizes.There
isaspecifiedsetoffoldersthatVSrecognizes,butyoucanaddyourownfolderlocation.
ToseewhattheVSsettingsare,selectTools|Options|Environment|Add-in/Macros
Security.You’llseeawindowsimilartoFigure13-8.TheAdd-in/MacrosSecurity
windowalsohasoptionsthatallowyoutodetermineifmacroscanrun,ifanyAdd-Inscan
load,orifAdd-InsareallowedtoloadovertheInternet.
Inadditiontothe*.AddInfile,you’llneedtodeterminewheretheAdd-Inclasslibrary
file(*.dll)willreside.Bydefault,theAdd-InProjectWizardassumesthatthe*.dllfileis
deployedinthesamelocationasthe*.AddInfile.Listing13-5showsthecontentsofthe
*.AddInfile.Thelocationofthe*.dllfileisspecifiedintheAssemblyelement,whichcan
beeitherafilesystempathoraURL.
<?xmlversion="1.0"encoding="UTF-16"standalone="no"?>
<Extensibilityxmlns=
"http://schemas.microsoft.com/AutomationExtensibility">
<HostApplication>
<Name>MicrosoftVisualStudio</Name>
<Version>10.0</Version>
</HostApplication>
<Addin>
<FriendlyName>KeystrokeFinder</FriendlyName>
<Description>
DisplaysaListofVSShortcutKeystrokes.
</Description>
<AboutBoxDetails>
CreatinganAdd-...
</AboutBoxDetails>
<AboutIconData>...</AboutIconData>
<Assembly>KeystrokeFinder.dll</Assembly>
<FullClassName>
KeystrokeFinder.Connect
</FullClassName>
<LoadBehavior>1</LoadBehavior>
<CommandPreload>1</CommandPreload>
<CommandLineSafe>0</CommandLineSafe>
</Addin>
</Extensibility>
AnotherwaytoworkwithAdd-InsisviatheAdd-InManager,whichyoucanopen
byselectingTools|Add-inManager.Figure13-9showstheAdd-InManagerwiththe
KeystrokeFinderAdd-Ininthelist.CheckingAvailableAdd-Insimmediatelyloadsor
unloadstheAdd-In,checkingStartupindicateswhethertheAdd-InwillloadwhenVS
starts,andcheckingCommandLinemakestheAdd-InloadifauserrunsVS(devenv.exe)
viathecommandline.
Chapter13: ExtendingVisualStudio2010 399
OncetheAdd-Inisdeployedandloaded,ausercanruntheAdd-InbyselectingTools|
KeystrokeFinder.WhentheAdd-Inruns,theOutputwindowwillcontainalistingof
commandsandshortcutkeys.Toseetheresults,youshouldopentheOutputwindow,
CTRL-W-O,beforerunningtheAdd-In.
NowyouknowhowtocreateanddeployanAdd-In,butyou’llalsoneedsome
guidanceinmovingforwardtohelpyoucreateyourownAdd-Ins.Thenextsection
providesthatguidance.
Where to Go Next
Asyou’veseeninprevioussections,theapplicationobjectiscentraltogettingstarted
withAdd-Indevelopment.Wheneveryouneedtofindsomething,usetheapplication
objectreference,presstheDOTonyourkeyboard,andIntellisensewillshowyou
propertiessuchascommandsandwindows.
Asyouviewtheapplicationobjectproperties,havetheVSdocumentationopen,
tellingyouwhateachpropertymeansandprovidingexamplecodeofhowitworks.
Sometimestherearen’texamplesandthedocumentationisn’tasclearasitcould
be.Inthosecases,youmighthavetoperformsomeinvestigation.Thetoolstoperform
400 MicrosoftVisualStudio2010:ABeginner’sGuide
thisinvestigationincludethedebugger’sbreakpointsandtheImmediatewindow.Seta
breakpointinoneoftheAdd-Inmethodsandinspectthevalueofanobject.Tofindout
whatisinsidethatobject,opentheImmediatewindow,typetheobjectname,andpress
DOTtoletIntellisensehelpyoufindpropertiesyou’reinterestedin.
Onoccasion,you’llhavepropertiesthatarecollections.Inthatcase,youcanwrite
codeintheAdd-Inmethodyouwanttheaccessthecollectionthrough,addaforeach(For
EachinVB)loop,andprintvaluesofthecollectiontotheOutputwindow.
Summary
EachsectionofthischapterwalkedyouthroughthestepsnecessarytowriteanAdd-In.
YoulearnedhowAdd-Inprojectsarestarted,similartootherprojects,exceptthatthe
wizardforcreatingAdd-Insismoreextensive.Onceyouunderstoodwhatprojectitems
werecreated,youlearnedaboutthecontentsoftheAdd-Initself,theinterfacesthat
areimplemented,andtheskeletoncodegeneratedbytheAdd-InProjectWizard.This
chaptershowedyouhowtoaddcodetotheAdd-Intomakeitperformasearchofall
VScommandsandtheirrelatedshortcutkeys.Thisprocessdemonstratedhowyoucould
accessanythingthroughoutVSviacode.YoulearnedhowtodeployandmanageanAdd-In
andthenfinishedoffwithtipsonmovingforwardtocreateyourownAdd-Ins.
Thisisthelastchapterofthisbook,butonlythebeginningforyoursoftwaredevelopment
experienceusingMicrosoftVisualStudio2010.Isincerelyappreciateyourreadingmybook
andhopethatitpropelsyoutogreaterskillandsuccess.
—JoeMayo
Part V
Appendixes
This page intentionally left blank
Appendix A
Introduction to XML
403
404 MicrosoftVisualStudio2010:ABeginner’sGuide
E xtensibleMarkupLanguage(XML)isanopen-standardscross-platformwayof
specifyingdocuments.Atitsorigins,XMLwasusedtorepresentdata,butithasgrown
inusetoincludeuserinterfacetechnologiesandevenexecutablelogic.Whilethereare
manypracticalusesofXML,thisbookismostlyconcernedwithexplaininghowXMLis
usedforASP.NET,Silverlight,andWindowsPresentationFoundation(WPF),allofwhich
arediscussedinchaptersofthisbook.Ineachofthesescenarios,somespecializationof
XMLisbeingusedtoconstructuserinterfaces.InASP.NET,youuseXMLforHTML
(XHTML).BothSilverlightandWPFuseXMLApplicationMarkupLanguage(XAML),
pronounced“Zamel.”BeforelearningaboutXHTMLorXAML,youmightwantan
introductionorrefresheronXML,whichisthepurposeofthisappendix.Whilethis
introductionwon’tteachyoueverythingaboutXML,itwillgiveyoutheessentialsthat
canhelpwhenseeinghowXMLisbeingused.
<?xmlversion="1.0"encoding="utf-8"?>
<customerid="7">
<name>Joe</name>
<address>1234thSt</address>
</customer>
AsyoucanseeinListingA-1,anXMLdocumentisreadabletext.Itcontainsdata,and
themeaningofthatdataisspecifictotheapplicationsthatneedtouseit.Thefollowing
sectionswilldecipherListingA-1andexplainwhateachpartofthedocumentmeans.
XML Prefixes
ThetopofthedocumentinListingA-1containsanXMLprefix,repeatedhereforconvenience:
<?xmlversion="1.0"encoding="utf-8"?>
AppendixA: IntroductiontoXML 405
Theprefixiscommonforlettingapplicationsreadingthedocumentknowthatitis
indeedanXMLdocument.Theversionisself-describing.Encodingisimportantbecause
itspecifiesthebinaryformatofthetext.Ifyouhaveoneapplicationpassingdatato
anotherapplication,it’simportantthatbothapplicationscanreadthedocumentandare
usingthesameencoding.Theutf-8encodingisthedefaultandforthepurposeofthis
bookistheonlyencodingyouwillcareabout.
Theanglebrackets,<and>,definethemarkupinXML.Forthefileprefix,contentis
placedbetween<?and?>charactersequences,butasthefollowingsectionsshow,most
othermarkupisdifferent.
XML Elements
TheXMLelementsinListingA-1arecustomer,name,andaddress.Eachelementis
definedbymatchingpairsofmarkup,followingthispattern:
<elementName>value</elementName>
Inthepreviousexample,elementNameisthenameoftheelementandvalueisthedata
associatedwiththatelement.Elementsalwayshaveabegintagandanendtag.Youcan
identifytheendtagbecauseitalwaysfollowsthebegintageventually(theremaybeother
elementtagsnestedinbetweenthepair)andcontainsaforwardslashcharacterbeforethe
elementname.
Thevalueinthepreviousexamplecansometimesbeblank,meaningthereisnovalue
forthatelement.Avaluecanalsobeoneormoreelements,suchascustomer,inListingA-1,
whichcontainsnameandaddresselements.InListingA-1,thevalueofnameisJoeandthe
valueofaddressis1234thSt.Inadditiontoelements,youcanhaveattributes,discussednext.
Attributes
Anattributedecoratesanelementwithasinglevalue,suchasinthefollowingexample:
<elementNameattributeName="attributeValue">
elementValue
</elementName>
Noticethattheattribute,attributeName,isinsideofthestarttagoftheelement.It
containsanequalsignandaquotedvalue.Youcanhavemultipleattributesonasingle
elementandthey’llbeseparatedbyspaces.Rememberthatattributescanhaveonlyone
value,butifyouneedtodefinemorethanonevalue,youmustuseelements.
ExamplesofattributesinListingA-1areversionandencodingintheprefixandid
oncustomer.
406 MicrosoftVisualStudio2010:ABeginner’sGuide
Namespaces
AnotherimportantpartofXMLthatyou’llneedtounderstandisnamespaces.InChapter2,
youlearnedhownamespacesinC#andVBhelpgiveauniqueidentitytocodewithina
givennamespace.ThepurposeofnamespacesinXMLissimilar.InthecaseofListing
A-1,thereisacustomerelement,butthinkabouthowmanydifferentprogramsworkwith
customerdata.Acustomerinoneprogramwillnotbedefinedthesameasacustomerin
anotherprogram,andyouneedawaytotellthemapart,whichiswherenamespacescome
in.Youwoulddefineyourcustomerdatainanamespaceofyourchoosing,andsomeother
developerwoulddefineauniquenamespacefortheircustomer.Thatway,yourprograms
won’teverbeconfusediftheytrytoreadthewrongdata.ListingA-2showshowtousea
namespacetomakeacustomerunique.
TIP
You might have noticed that the namespaces in Listing A-2 look like Web addresses.
However, this is just coincidence and is a common practice used to increase the chance
that the namespace is unique. In reality, the namespace is just a string, which catches
people new to namespaces off guard. For example, http://mcgraw-hill.com/vs2010bg
is a different namespace than http://mcgraw-hill.com/vs2010bg/ because the extra
forward slash on the end is a different string. So, if you made this mistake, then it’s
possible that a program won’t recognize the data as being a valid format because the
data is in a different namespace than what the program expects. Remember that a
namespace is a unique string, not a Web address.
<?xmlversion="1.0"encoding="utf-8"?>
<customerid="7"
xmlns="http://mcgraw-hill.com/vs2010bg"
xmlns:a="http://somedomain.com/addresses">
<name>Joe</name>
<a:address>1234thSt</a:address>
</customer>
Namespacesarespecifiedbyplacinganxmlnsattributeonanelement,eitherwith
orwithoutaprefix.Thexmlnswithoutaprefixspecifiesthedefaultnamespaceforallof
theelementswherethenamespaceresidesandchildelementsoftheelementwherethe
namespaceresides.Thismeansthatcustomerandnameareinthehttp://mcgraw-hill.com/
vs2010bgnamespace.
Namespacescanalsohaveprefixestohelpyoutargetwheretheyareapplied.In
ListingA-2,thereisanxmlns:a,whereaistheprefixforthehttp://somedomain.com/
AppendixA: IntroductiontoXML 407
addressesnamespace.TheconvenienceofprefixesisthattheyhelptheXMLbemore
readable.InListingA-2,theaddressnamespaceisdecoratedwiththea:prefix,asin
<a:address>toindicatethataddressbelongstothehttp://somedomain.com/addresses
namespace.Withouttheprefix,youwouldbeforcedtowritetheaddresselementas
follows,whichismoredifficulttoread:
<http://somedomain.com/addresses:address>
1234thSt
</http://somedomain.com/addresses:address>
Iaddedlinebreaksforreadability,butinpracticetheonlypartofthedatareadisthe
valueandnotthewhitespace,suchasnewlines,surroundingit.
Summary
YoushouldnowunderstandthebasicsofworkingwithXMLinVS.Youlearnedhowto
createanXMLdocumentandwhatprefixes,elements,attributes,andnamespacesare.
YoualsolearnedhowtofindtheXMLoptionstocustomizeyourXMLdocument-editing
experience.XMListhefoundationuponwhichXAMLandXHTMLarebased,which
iscoveredinlaterappendices.ThisshouldgiveyoufamiliaritywiththeXMLthatis
presentedinthechaptersofthisbook.
This page intentionally left blank
Appendix B
Introduction to XAML
409
410 MicrosoftVisualStudio2010:ABeginner’sGuide
X MLApplicationMarkupLanguage(XAML),pronounced“Zamel,”isanXML-
basedlanguageforbuildinguserinterfaces.You’llfindXAMLbeingusedinboth
WindowsPresentationFoundation(WPF)andSilverlightapplications.WPFisfordesktop
applicationdevelopment,andSilverlightisforWeb-baseddevelopment.BothWPFand
SilverlighthavemuchincommonthroughprogrammingwithXAML.Therefore,this
AppendixprovidesanintroductiontoXAMLandshowsyouhowtoperformlayouts,
whicharecommontobothWPFandSilverlight.ThisAppendixcanbeusefulbefore
readingtheWPFandSilverlightchapterssothatyoucangetthemostoutofwhatis
specifictoeachtechnology.Forsimplicity,I’lldemonstrateconceptsbyusingaWPF
application,butwhatyoulearnwillbeapplicabletobothWPFandSilverlight.Before
readingthisAppendix,youmightwanttoreadorreviewAppendixAforanintroduction
toXML,whichwillprovideyouwithfamiliarityofbasicXMLsyntax.
<Windowx:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"Height="350"Width="525">
<Grid>
</Grid>
</Window>
InVS,thedefaultlayoutforWindow1.xamlistohaveavisualdesigneronthetophalf
oftheworkwindowandXAMLinthelowerhalf.YoucanviewthefullXAMLdocument
bygrabbingthetopedgeoftheXAMLhalfanddraggingittothetopofthescreensothat
youareonlylookingattheXAMLeditor.ThefirstthingyoushouldnoticeaboutListingB-1
AppendixB: IntroductiontoXAML 411
isthatitisanXMLdocumentwithelements,attributes,andnamespaces.Eachofthe
itemsyouseehasspecialmeaning,aswillbediscussedinthefollowingsections.
Elements as Classes
ForXAMLtobemeaningfulascode,elementsmustbeassociatedwithclasses.The
WindowelementinListingB-1isassociatedwithaclassnamedWpfApplication1
.MainWindow,specifiedbythex:Classattribute.Thexprefixaliasesthehttp://schemas
.microsoft.com/winfx/2006/xamlnamespace,wheretheClassattributeisdefined.By
mappingtheelementtoaclass,youallowVStocompiletheXAMLintocodethatruns.
Noticethatthedefaultnamespaceishttp://schemas.microsoft.com/winfx/2006/xaml/
presentation,whichdefineshoweachoftheelementswithoutprefixeswillbecompiled
tocode.TheimportantfacttorealizehereisthatwhenwritingXAML,youarecreating
adocumentthatwillbetranslatedintoexecutablecodeforyouatcompiletime.
Attributes as Properties
Title,Height,andWidthareattributesoftheWindowelementinListingB-1.WhenVS
compilestheXAML,eachoftheattributesofelementswillbetranslatedtoproperties
oftheclassthattheelementistranslatedto.Morespecifically,theWpfApplication1.
MainWindowclasswillhaveTitle,Height,andWidthproperties.Eachoftheproperties
willbesetwiththevalueassignedtotheircorrespondingattributes.
Property Elements
You’veseenhowattributestranslatetoproperties.Inadditiontoattributes,XAMLhas
propertyelements,whicharechildelementswhereoneormoreotherelementsbecome
assignedtoaproperty.AnexampleofapropertyelementwouldbetheContentproperty
ofaButton.AButtonisaclassinbothWPFandSilverlightthatausercanclickto
producesomeactioninyourprogram.TheContentpropertyoftheButtondetermines
whattheusersees.Todescribethedifferencebetweenapropertyattributeandaproperty
element,I’llshowyouanexampleofbothwiththeContentpropertyoftheButtonclass.
ListingB-2showsaButtonwithitsContentsetasanattribute.
<Windowx:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"Height="350"Width="525">
<ButtonContent="ClickMe"/>
</Window>
AppendixB: IntroductiontoXAML 413
InListingB-2,youcanseethattheWindowhasacontainedButtonelementwhose
Contentattributecontainstext.FigureB-2showswhatthislookslikewhenrunning.
ApowerfulfeatureofXAMLispropertyelementsthatallowyoutoaddsophisticated
markupthatwillbeassignedtoaclassproperty.InthecaseoftheButton,we’llenhance
theContentpropertyasapropertyelementinXAMLtoshowhowtoaddcontentother
thantext.ThefollowingmarkupistheButtonfromListingB-2,enhancedtoholdan
imageinsteadoftext.Forreadability,IaddedalinebreakforthevalueoftheSource
attribute:
<Button>
<Button.Content>
<ImageSource=
"C:\Users\Public\Pictures\SamplePictures\Penguins.jpg"/>
</Button.Content>
</Button>
InsteadofsettingtheContentattribute,theprecedingexampleusespropertyelement
syntax,wherethechildelementisnamed<parentElementName.attributeName>.The
benefitofpropertyelementsyntaxshownintheprecedingcodeisthattheContent
propertywillnowbesettoanimage.Withattributesyntax,youwerelimitedtotext,but
withpropertyelementsyntax,youcanputanythinginabutton.Ofcourse,insteadofwhat
Ididwiththeimage,youwouldwanttousecommonsenseandonlyaddcontentthatis
meaningfulfortheapplication.FigureB-3showsthenewbuttonwiththeimage.
414 MicrosoftVisualStudio2010:ABeginner’sGuide
TIP
VS provides XAML editor support by allowing you to place your cursor between begin
and end tags, pressing ENTER, and indenting the start position of the cursor on the new
line between the start and end tags. From that point, you can type < and begin working
with Intellisense to select the element and attribute you need to implement with property
element syntax.
Markup Extensions
AnotherextensibilitypointinXAMLismarkupextensions,whichallowyoutosetan
attributetoreferenceanothervalue.Commonusesofmarkupextensionsincludedata
bindingandresourceusage.Databindingisthepracticeofassociatingdatawithauser
interfacecontrol.Forexample,ifyouneededtoshowacustomerrecordonthescreen,
youwouldbindeachpropertyofthecustomerobjecttopartsofthescreen,suchas
bindingacustomernametoaTextBoxonthescreen.You’llseeexamplesofdatabinding
intheWPFandSilverlightchaptersofthisbook,Chapters8and10.Rightnow,it’s
importanttoconcentrateonwhatamarkupextensionis,andyou’llseeanexamplethat
appliesaresourcetoanelement.
Aresourceissometypeofobjectorvaluethatcanbeusedbymultiplecontrols.For
example,youcandefineaspecialcolorforbuttonsonyourscreeninoneplaceandthen
useamarkupextensiontopointallofthesebuttonstothesameresource.Thatway,you
canchangethecolorresourceinoneplaceandallbuttonsreferringtothatcolorresource
AppendixB: IntroductiontoXAML 415
willchangeautomatically.ListingB-3definesabrushresourceofaspecificcolorand
showshowtoreferencethatbrushfrommultiplebuttonsusingamarkupextension.
<Windowx:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"Height="350"Width="525">
<Window.Resources>
<SolidColorBrushx:Key="ButtonBrush"Color="Yellow"/>
</Window.Resources>
<StackPanel>
<ButtonBackground="{StaticResourceResourceKey=ButtonBrush}"
Content="ButtonOne"/>
<ButtonBackground="{StaticResourceResourceKey=ButtonBrush}"
Content="ButtonTwo"/>
</StackPanel>
</Window>
TheWindow.ResourceselementinListingB-3isapropertyelementofWindow.It
containsaSolidColorBrushwithColorsettoYellow.EverythinginWPFandSilverlight
isdrawnwithbrushes,whichdefinecolors,gradients,images,media,orpatterns.Inthis
case,we’llkeepitsimplewithasinglecolor,whichiswhatSolidColorBrushisgoodfor.
Thepointhereisnotwhatabrushis,butthefactthatthebrushisaresourcethatwill
helpdemonstratehowtouseamarkupextensiontoaccessthatresource.It’simportantto
assignakeytoeveryresourcebecausethatkeyiswhatresourcemarkupextensionsuseto
identifytheresource.
YoucanseethemarkupextensionassignedtotheBackgroundattributesoftheButton
elementsinListingB-3.Markupextensionsaresurroundedbycurlybraces.Withinthe
curlybracesaretheextensiontypeandattributesassociatedwiththeextension.InListing
B-3,theextensiontypeisStaticResource,whichallowsyoutorefertoaresource.The
ResourceKeyattributeoftheStaticResourceextensionspecifiestheparticularresource
touse.Thevalue,ButtonBrush,matchesthekeyoftheSolidColorBrushresource.So,
thevalueoftheBackGroundattributeoftheButtonelementsisaStaticResourcefora
SolidColorBrushthathasitscolorsettoYellow.ThiseffectivelymeansthattheButtons
willhaveYellowbackgrounds.
Toseethevalueofusingresources,considerthesituationyouwouldbeinifyou
settheBackGroundattributeofeachbuttondirectlytoYellowinsteadofusingthe
416 MicrosoftVisualStudio2010:ABeginner’sGuide
FigureB-4 Two Buttons using the same resource via a markup extension
StaticResourcemarkupextension.Further,thinkabouttheamountofworkyouwould
needtodoifyouwantedtochangethebackgroundcolorofallbuttons,resultingin
recodingeachindividualbutton.However,withtheStaticResourcemarkupextension,you
canchangethecolorintheSolidColorBrushresource,andtheBackGroundofallbuttons
willchangewithoutanyadditionalwork.FigureB-4showseachofthebuttons.Though
youcan’ttellthebackgroundcolorinthegrayscaleofthisbook,Ipromisethattheyare
yellow.
Summary
ThisappendixintroducedyoutoXAML,whichistheXMLdocumenttypeusedtobuild
userinterfacesforWPFandSilverlight.Youlearnedthatelementsmaptoclassesand
attributesmaptoclassproperties.Youalsolearnedhowtospecifypropertyelements
togainmorecontrolthanwhatyoucangetwithattributesalone.Finally,youlearned
aboutthesyntaxofamarkupextensionandhowtheStaticResourcemarkupextension
allowsyoutoreferenceresources.You’renowreadytoapproachtheWPFandSilverlight
chaptersinthisbook,whichuseXAMLheavilytobuildtheiruserinterfaces.
Index
Symbols buildingwithASP.NETMVC,262–264
Click-Once,120
<>(anglebrackets),405 COM,121,124,134
{}(braces),40,57,160 compiling,129–135
?(questionmark),162 Console.SeeConsoleapplications
_(underline),55 includingdatabaseswith,253
/integer,62 Java,300–301
&operator,62 MicrosoftOffice,124
+operator,62 OOB,294–297
outputpath,134
Silverlight,285–298
A stateof,160–166
Web,152–153
accessors,84,86 WindowsServices,33
AddReferencewindow,122–123 WPF.SeeWPF
Add-InProjectWizard,372–383,398 Architecturemenu,15
add-ins,371–400 arguments,75–78,153
addingfunctionalityto,383–397 arrays,62–63,107–108
creating,372–383 artifacts,116,117,136
deploying,397–399 ASP.NET
generalinformation,372,399–400 deployingWebservices,315,317,
Analyzemenu,15 325–326,336
anglebrackets<>,405 described,250
anonymoustypes,198–199,206 ASP.NETMVC,249–284
API(applicationprogramminginterface),5 buildingapplications,264–284
applicationicons,120 creatingControllers,254–256,268–269
applicationprogramminginterface(API),5 creatingModels,254
applications displayingViews,256–261
artifacts,116,117,136 managingrouting,262–264
417
418 MicrosoftVisualStudio2010:ABeginner’sGuide
ASP.NETMVC(continued) capitalizationissues,40,53
MVCobjects,250–254,270–276 CascadingStyleSheets(CSS),252,344
overview,250–251 casesensitivity,40,53
startingASP.NETMVCproject,251–254 charactersets,174
ASP.NETMVCProjectWizard,261 childclasses,70,71
ASP.NETprojects,33 child/parentrelationship,187–192,206
assemblies,114,119,122–129 ClassDesigner,137–141
AssemblyInformationoption,118,121–122 codegeneration,138–141
assemblyname,118,119 using,137–141
assemblyreferences,122–129 visualizingcodewith,137–138
associations,201 classlibraries,33,36–38,125–129
authentication,184,319,322 ClassLibraryprojects,119,124,125–129
automaticproperties,85–86 classlocators,44
Autoswindow,160–161,162 classsnippet,71–72
classtype,68
Classview,136
B classes
child,70,71
backingfield,85,86 creating,68–72
binding,234–247 creatingforinterfaces,98–101
bookmarks,44–45 customdefinitions,68–70
braces{},40,57,160 debuggingand,148
branchingstatements,57–61 finding,44
breakpoints,155–158 inheritance,70–72
conditional,172 instantiatingobjectsfrom,69
creating,156–157 parent,70
customizing,157–158 Program,41–42
managing,158 snippets,71–72
overview,155 syntax,68–70
using,171–173 WCF,308–314
bugs,167–179.Seealsodebugging cleaningsolutions/projects,130–131
buildeventmacros,134 clickevents,228–234,246
buildorder,131–132 Click-Onceapplications,120
CLR(CommonLanguageRuntime),154
code.Seealsoprogramminglanguages;programs
C automaticallygenerated,4–5
breakpointsin.Seebreakpoints
C#compiler,133,135 CallHierarchyfeature,148–150
C#language callsites,148–150,163
casesensitivity,40,53 inclasslibraries,126–129
codeeditoroptions,46–47 debugging.Seedebugging
considerations,13 generatingwithClassDesigner,138–141
includedwithVisualStudio,36 hierarchicalmodel,114–115
inheritance,70 IntelliTrace,165–166
Intellisense,50–51 forinterfaces,101–106
popularityof,36 managed,154
primitivetypes,53 onMcGraw-HillWebsite,103
vs.VBlanguage,13,36,115–116 PinToSourcefeature,164–165
C++language,31,36,154,373 reusing,149
C#projects,31,33,115–116,150,151.Seealso skeleton,4–5,39–43
projects snippets.Seesnippets
CallHierarchyfeature,148–150 steppingthrough,158–159
callsites,148–150,163 unmanaged,154
CallStackwindow,163 unsafe,133,134
Canvaslayout,225–226 usinginclasslibraries,126–129
visualizingwithClassDesigner,137–138
Index 419
codeeditor.SeeVSCodeeditor .csextension,68
codelibraries.Seeclasslibraries CSS(CascadingStyleSheets),252,344
code-behindfile,228–234 customtypes,52
coding,49–66.Seealsospecificlanguages Customerclass,167
branchingstatements,57–61 CustomerRepositoryclass,168–171
classes.Seeclasses
debugging.Seedebugging
enums,55–57
expressions.Seeexpressions
D
Intellisense.SeeIntellisense data,181–214.Seealsodatabases
methods.Seemethods addingtotables,186–187
primitivetypes,52–54 binding,234–247
runningprograms,51–52 dirty,173
snippets.Seesnippets displayingingrid,244–247
toolsfor,148–150 handlingwithLINQtoSQL,200–214
VSfeatures,4–5 queryingwithLINQ,194–214
Webservicecalls,329–336 reading/saving,243–244
collections workingwithinWPF,234–247
advantagesof,110 datamodel,200
generic,107–110 datasources,234–241,244
object,194–197 databasediagram,190–192
vs.arrays,62–63 databaseprojects,34
colorschemes,25 databases,182–194.Seealsodata
COM(ComponentObjectModel)applications,121, authentication,184
124,134 connectionsto,183–184
COMInterop,133,134 creating,183–184
COMobjects,124 includingwithapplications,253
ComboBoxcontrol,241–243 ServerExplorer,182–193
command-linearguments,153 settings,193–194
CommonLanguageRuntime(CLR),154 storedprocedures,192–193
compilerconstants,150 tables.Seetables
compilers DataGridoption,244–247
assemblyreferences,123 Debugclass,133–134
C#,133,135 DEBUGcompilationconstant,133–134,150
considerations,4,86,96 Debugconfigurations,150,153
errors/warnings,123,134,204,344 Debugmode
optimizations,150,152 configuring,150–155
settings,133–135 runningprogramsin,156,171
VB,134–135 startingprogramsin,156,171
compilingapplications,129–135 DebugOutputfolder,151,152
ComponentObjectModel.SeeCOM debugproperties,152–155
compression,131 debugging,143–180
computationexpressions,54 applicationstate,160–166
conditionalbreakpoints,172 CallHierarchyfeature,148–150
Connectclass,378–383 CallStack,163
Consoleapplications configuringDebugmode,150–155
creating,37–39,115–116 described,51
debugging,144–179 evaluatingexpressions,151–152,162
described,32,36 findingbugs,171–174
skeletoncode,39–43 fixingbugs,174–175
contextsensitivity,16 history,166
ControlLibraries,33 nullreferenceexceptions,175–179
controls.Seealsospecificcontrols properties,150–155
Silverlight,290–293 onremotemachines,153–154
WPF,226–234 runningapplications,152–153
420 MicrosoftVisualStudio2010:ABeginner’sGuide
debugging(continued) controllers,278
runningprogramswithdebugging,52 nullreferenceexceptions,93,175–179
runningprogramswithoutdebugging,51 vs.warnings,134
sampleprogramwithbugs,167–179 eventhandlers,91,95–96,228–234
startingprogramsinDebugmode,156,171 eventkeyword,93
storedprocedures,154 EventHandlerclass,94–95
VSDebugger,166–179 events,91–93.Seealsodelegates
.vshostfiles,151–152 click,228–234,246
Webapplications,152–153 codecompletionfor,95–96
delegates,90,94–96.Seealsoevents described,90,91
Delphilanguage,5 diagnostic,165–166
dependencies,131–133 example,91–93
development-timecodetools,148–150 handling,228–234
diagnosticevents,165–166 null,93
directories useof,91–93,95
CreateDirectory,116 .exeextension,119
name,317 Execmethod,391–395
physical,328 ExportTemplateWizard,346
virtual,315 expressions
dirtydata,173 branching,57–59
.dllextension,119,124 considerations,49
doloops,65–66 described,54
dockingwindows,18–19 evaluatingduringdebugging,
DockPanellayout,223–224 151–152,162
documentation,11 performingcomputations,54
DynamicDataprojects,33 primitivetypes,54
viewing,163–164
ExtensibleMarkupLanguage.SeeXML
E
Editmenu,14 F
elements
accessing,110 F#language,31,36
inarrays,107–108 false/trueconditions,55,57,62
asclasses,411 fields
ingenericlists,109–110 backing,85,86
property,412–414 considerations,81,83
elsesnippets,58–59 declaring,81–83
elsestatements,58–59 described,69,81
EnableManagedCodeoption,154 exampleof,68,69
endlessloops,157 using,81–83
enums,55–57 vs.properties,83
environment filelocks,154
IDE,4,13 Filemenu,14
macros,134,342,360–370 FilePropertieswindow,122
snippets.Seesnippets FileTransferProtocol(FTP),315,317,319
templates.Seetemplates files
environmentsettings code-behind,228–234
considerations,13 compressing,131
default,11,12–13,28–30,31 .dll,124
exporting,23–24 hidden,117–118
importing,24–28 log,7,166
modifying,13,22–30 .pdb,151
resetting,28–30 project,116–121
errors.Seealsowarnings .vshost,151–152
compiler,123,134,204,344 XML,134
considerations,134 floatingwindows,19–20
Index 421
folders integrateddevelopmentenvironment(IDE),4,13
hierarchyof,116–118 Intellisense
projects,116–118 C#options,50–51
snippets,358–359 ConsumeFirstmode,47
solutions,116–118 described,5
forloops,61–64 savingkeystrokeswith,49–51
foreignkeys,187–192 snippetcompletionlists,47,49,50
FTP(FileTransferProtocol),315,317,319 Standardmode,47
switchingbetweenmodes,47
using,49–51
G writingexpressions,163
IntelliTracewindow,165–166
GAC(GlobalAssemblyCache),122–123 interfacesnippets,106
genericcollections,107–110 interfaces,96–106
genericlists,109–110 creating,97
getaccessors,84,86 creatingclassesfor,98–101
GlobalAssemblyCache(GAC),122–123 modifying,97
Global.asaxfile,253 overview,96
GloballyUniqueIdentifier(GUID),121 WCF,302–308,377–383,389
graphicaluserinterface(GUI),95 writingcodefor,101–106
Gridlayout,220–222 InternetInformationServer(IIS),314–326
GUI(graphicaluserinterface),95 itemtemplates,347–353
GUID(GloballyUniqueIdentifier),121 items.Seeprojectitems
H J
Helpmenu,15 Javaapplications,300–301
hiddenfiles,117–118 JavaScript,253,257,272,288
HTML(HypertextMarkupLanguage) joins,205–209
considerations,260
helpermethods,272–273,278
viewingcode,256–261
XHTML,404
K
keyboardshortcuts,15,44,47
keywords,47
I
.icoextension,120
Iconsetting,118,120
L
icons,16–17,120,236,295 LanguageIntegratedQuery.SeeLINQ
IDE(integrateddevelopmentenvironment),4,13 languages
ifsnippets,58–59 C#.SeeC#language
ifstatements,57–59 C++,31,36,154,373
IIS(InternetInformationServer),314–326 Delphi,5
immediateifoperator,55 F#,31,36
Immediatewindow,162 HTML.SeeHTML
impedancemismatch,201 includedwithVS2010,36
Implementskeyword,101 VisualBasic.SeeVB
ImportandExportSettingsWizard,22–32,45 WSDL,301
Importsdirective,129 XAML.SeeXAML
indicatormargin,44 XML.SeeXML
inheritance,70–72 libraries.Seeclasslibraries
instancemethods,74–75 libraryfiles.Seeassemblies
instances,40–41,129,148 licensekey,8
inttype,78,80 licensingterms,7–8
Integerkeyword,54 LINQ(LanguageIntegratedQuery),186,194–214
422 MicrosoftVisualStudio2010:ABeginner’sGuide
LINQprojections,198–199 MicrosoftOfficeapplications,124
LINQtoSQL,200–214 MicrosoftOfficeprojects,34
creatingitems,305 ModelViewController.SeeASP.NETMVC
deletingdata,212–214 MSDN(MicrosoftDeveloperNetwork),6,326
insertingdata,210–211 MVCobjects,250–254,270–276.SeealsoASP.NETMVC
multipletables,205–210
overview,200
querying,203–210
settingup,200–201
N
updatingdata,211–212 namespacesnippet,47–48
WPFapplications,246–247 namespaces
LINQtoSQLDesigner,200–203 assemblyreferencesand,122
LINQtoSQLWizard,200,205 default,116,119,328,406
ListBoxcontrol,241–243 overview,42–43
lists,generic,109–110 Root,119
localvariables,81 setting,119
Localswindow,160–161,162 VB,43
logfiles,7,166 XML,406–407
loops,61–66 namingconventions,40–43,116,231
endless,157 .NETassemblyreferences,123–124
for,61–64 .NETCLR.SeeCLR
while,64–65 .NETFramework,38,90,119,124,320
.NETFrameworkClassLibrary,13
.NETtypes,53–54
M NewProjectwindow,37,115–116
NewProjectWizard,39,253
MacroEditor,365–370,374,380 nullevents,93
MacroExplorer,364–365 nullreferenceexceptions,93,175–179
macros,134,342,360–370 nullvalues,176–179
Mainmethod,40–41,49,120
manifest,120–121
Manifestsetting,118,120–121
markupextensions,414–416
O
MasterPages,257–260,270,273 objectcollections,194–197
mathematicaloperators,54 objects
McGraw-HillWebsite,103 COM,124
memberlocators,44 creating,139
Memorywindow,173 debuggingand,148
menubar,14–15 instantiatingfromclasses,69
methodresults,78–80 MVC,250–254,270–276
methods,72–80.Seealsospecificmethods Officeapplications,124
addingparametersto,75–78 Officeprojecttypes,124
calling,72–75 Officeprojects,34
declaring,72–75 OnConnectionmethod,384–391
delegates.Seedelegates OOB(Out-of-Browser)functionality,294–297
events.Seeevents operatingsystems.SeespecificWindowssystems
instance,74–75 operators
naming,40–41,231 immediateif,55
overview,72 mathematical,54
private,74 ternary,55,57
public,74 optimization,131
returningvaluesfrom,78–80 Optionsmenuitem,15
shared,74 Optionswindow,45,46,154–155
snippets,80 OtherWindowsmenuitem,14
static,41,74 Out-of-Browser(OOB)functionality,294–297
using,72–75 Outputtype,119–120
MicrosoftDeveloperNetwork(MSDN),6,326 OutputTypesetting,118,119–120
Index 423
P propertysettings,118–122
recent,116
parameters,75–78 referencingassemblies,122–129
parentclasses,70 resettingreferences,126
parent/childrelationship,187–192,206 savingastemplates,344–346
.pdbfiles,151 searchingfor,38
PinToSourcefeature,164–165 SharePoint,34
primarykeys,186–189,191,201 Silverlight,285–298
primitivetypes,52–54 sorting,38
privatemodifier,83 templatesfor.Seetemplates
privatevariables,85 typesof,30–34
productkey,8 viewingavailable,30–32
Programclass,41–42,44,137 viewingwithClassDesigner,
programminglanguages.Seealsolanguages 137–141
C#.SeeC#language WCF.SeeWCF
C++,31,36,154,373 web,33,286
Delphi,5 WindowsProjects,32–33
F#,31,36 WPF.SeeWPF
includedwithVS2010,36 properties
VisualBasic.SeeVB accessors,84
programs.Seealsocode automatic,85–86
debugging,52,156,171 debug,150–155
pausingexecutionof,157 declaring,81–86
running,51–52 described,81
projectitems,21,86,116 exampleof,83–84
ProjectPropertieswindow,118–122 projects,118–122
projections,198–199 setting,228
projects.Seealsosolutions using,81–86
addingtosolutions,117–118 vs.fields,83
artifacts,116,117,136 Propertiesfolder,117,118
ASP.NETMVC.SeeASP.NETMVC Propertieswindow,118–122,139,227–233
“barebones,”36–39 propertyelements,412–414
buildorder,131–132 propertysnippet,86
building/rebuilding,129–130 publicaccessmodifier,74
C#,31,33,115–116,150,151
C#vs.VB,115–116
ClassDesignervisualization,137–138 Q
ClassLibrary,119,124,125–129
cleaning,130–131 queries.SeealsoLINQtoSQL
compilersettings,133–135 onmultipletables,205–210
Console.SeeConsoleapplications objectcollections,194–197
creating,36–39,115–116 storedprocedures,192
database,34 QueryStatusmethod,395–397
deleting,116 questionmark(?),162
dependencies,131–133 QuickWatchwindow,163–164
folders,116–118
hiddenfiles,117–118
hierarchicalrelationships,116–118
location,37
R
MicrosoftOffice,34 refactorings,5
modifying,343–344 ReferencePaths,125
naming/renaming,37,115–116,119,126 references
navigatingwithClassview,136 addingtoCOMobjects,124
new,31–32 assembly,122–129
optimizing,131 classlibraries,125–126
organizingprinciples,114–115 external.dllfilesand,124
overview,31–32 resetting,126
424 MicrosoftVisualStudio2010:ABeginner’sGuide
Releaseconfigurations,150,153 opening/closingitems,21
releases,6,11,12 overview,16
remotedebugging,153–154 workingwithcontrols,227
repository,265–268,282 solutionfolders,116–118
resources,referencing,414–416 solutions.Seealsoprojects
Resourcesoption,121 addingprojectsto,117–118
Rootnamespace,119 artifacts,116,117,136
routing,262–264 building/rebuilding,129–130
cleaning,130–131
contents,38–39
S described,38
folders,116–118
scope,160–161 hierarchicalrelationships,
searchfeatures,38,158 116–118
selectstatement,59–60 naming,115–116
serializationassemblies,133 organizingprinciples,114–115
ServerControlprojects,33 showing,116–117
ServerExplorer,182–193 sorting/searchingfeatures,38,158
servicereference,326–334 sourcecode.Seecode
servicereleases,6,11,12 sourcecontrol,116
setaccessors,84,86 SQL.SeeLINQtoSQL
sharedmethods,74 StackPanellayout,222–223
sharedmodules,41 Startpage,15
SharePointprojects,34 Startupobject,118,120
shortcutkeys,15,44,47 statements
Silverlight,285–298,326,336.SeealsoXAML branching,57–61
Silverlightapplications,285–298 considerations,49
skeletoncode else,58–59
automaticallygenerated,4–5 if,57–59
Consoleapplication,39–43 usingIntellisensewith,49–51
.snippetextension,354 statickeyword,40
snippets staticmethods,41,74
class,71–72 Statusbar,16
creating,353–358 StepOveroperation,159
doloops,65–66 storedprocedures
else,58–59 databases,192–193
examining,354–356 debugging,154
foreachloops,63–64 inLINQtoSQL,209–210
forloops,62 SubMainmethod,40
ifstatements,58–59 switchstatement,59–61
interface,106 switchstatementsnippets,60–61
libraryof,358–359 systemicons,120
method,80 Systemnamespace,42,43
namespace,47–48 systemrequirements,6
overview,47–48
picklist,47
property,86
switchstatement,60–61
T
using,47–48 tabbedwindows,20–21
whileloops,64–65 tables
snippetsfolders,358–359 addingdatato,186–187
SnippetsManager,359 addingtodatabases,185–187
SolutionExplorer,116–118 considerations,201,202
Consoleapplicationcreation,38 foreignkeys,187–192
managingbuildorder,131–132 multiple,187–192,205–210
managingdependencies,131–133 performingquerieson,205–210
Index 425
targetframework,119 local,81
TargetFrameworksetting,118,119 primitivetypes,52–54
TeamFoundationServer(TFS),15 private,85
Teammenu,15 inscope,160–161
templates watchinginWatchwindow,161–162
creating,343–347 watchingwithPinToSource,164–165
exporting,344–346 VB(VisualBasic.NET)
implementing,342–353 considerations,13
item,347–353 inheritance,70
options,345–346,352–353 popularityof,36
overview,342–343 primitivetypes,53
savingprojectsas,344–346 vs.C#language,13,36,115–116
ternaryoperator,55,57 VBcompiler,134–135
Testmenu,15 .vbextension,68
TFS(TeamFoundationServer),15 VBnamespaces,43
titlebaricons,16,17 VBprojects.Seealsoprojects
toolbar,15 assemblyreferences,124
Toolbox naming,116
ClassDesigner,138–139 targetframework,119
generalinformation,16–20 vs.C#projects,115–116
workingwithcontrols,227–228 VBA(VisualBasicforApplications),34
Toolsmenu,15 Viewmenu,14
Traceclass,133–134 Views,256–261
TRACEcompilationconstant,133–134,150 virtualdirectories,315
true/falseconditions,55,57,62 VisualBasicforApplications.SeeVBA
types.Seealsospecifictypes VisualBasic.NET.SeeVB
anonymous,198–199,206 VisualDesigner,191,220,227,228
class,68 VisualStudio2010.SeeVS2010
considerations,41 VisualStudioHostingProcess,154
custom,52 VisualStudioprojects,30–34.Seealsoprojects
described,68 voidkeyword,40,74
.NET,53–54 VS(VisualStudio)2010
Officeprojects,124 add-ins.Seeadd-ins
primitive,52–54 described,4
documentation,11
installing,6–13
U interface,13–16
languagesincludedwith,36
UAC(UserAccountControl),120 licensekey,8
underline(_),55 licensingterms,7–8
Untilcondition,65 managingwindows,16–21
Untilkeyword,65 modifyingenvironmentsettings,22–30
UserAccountControl(UAC),120 navigating,13–16
userinterface,226,234,251,404 privacystatement,7
usingdirectives,43,129 productkey,8
releases,6,11,12
restoringdefaultsettings,28–30,31
V starting,13–14
systemrequirements,6
valuekeyword,84 versions,6,7
values VSCodeeditor,45–48
null,176–179 VSDebugger,166–179
returningfrommethods,78–80 VSeditor,5
variables VSRecentProjectslist,116
applicationstate,160–166 VS2010ImageLibraryfile,120
described,52 .vshostfiles,151–152
426 MicrosoftVisualStudio2010:ABeginner’sGuide
W WindowsVistasystems,6,34
WindowsXPsystems,6,34
warnings,23,134,189,190.Seealsoerrors wizards
Watchwindows,161–162 Add-InProjectWizard,372–383,398
WCF(WindowsCommunicationFoundation),299–338. ASP.NETMVCProjectWizard,261
SeealsoWebServices ExportTemplateWizard,346
communicatingwithWCFservices,326–338 ImportandExportSettingsWizard,22–32,45
hostingWCFservices,314–326 LINQtoSQLWizard,200,205
overview,300–301 NewProjectWizard,39,253
startingWCFprojects,301–314 optionsfor,5
WCFclasses,308–314 workarea,15
WCFcontract,302–308 workingdirectory,153
WCFprojects,301–314 WPF(WindowsPresentationFramework),
WCFservices.SeeWebservices 217–247
Webapplications bindingdata,234–247
buildingcontrollers,254–256 Click-Onceapplications,120
creating,251–254 controls,226–234
creatingmodels,254 layouts,220–226
customermanagement,264–284 outputtypes,120
debugging,152–153 startingprojects,218–220,410–411
displayingviews,256–261 workingwithdatain,234–247
managingrouting,262–264 XAML.SeeXAML
portal-style,34 WrapPanellayout,224–225
webprojects,33,286 WSDL(WebServiceDescriptionLanguage),301
WebServiceDescriptionLanguage(WSDL),301
Webservices,299–338.SeealsoWCF
addingtoWebsites,337–338 X
communicatingwith,326–338
hostingonIIS,314–326 XAML(XMLApplicationMarkupLanguage),409–416
overview,300–301 attributes,411
proxies,328–333 considerations,218
usedbyclients,336–337 controls,227
WebServicesprojects,33 elements,411
Websites markupextensions,414–416
addingWebservicesto,337–338 overview,410
creatingonIIS,315,317–321 propertyelements,412–414
deployingSilverlightapplicationsto,297–298 Silverlightprojects,286–290
deployingWebservices,315,317,325–326,336 startingWPFprojects,218–220,410–411
web.configfile,253 WPFcontrols,228
whileloopsnippets,64–65 XAMLdocuments,executing,411–412
whileloops,64–65 .xamlextension,227
Win32resourcesfile,121 XHTML(XMLforHTML),404
windows,managing,16–21 XML(ExtensibleMarkupLanguage)
Windows7systems,6,34,315–317 introductionto,403–407
Windows2003systems,6 WCFservices,300–301,330
Windows2008systems,6,34,300,321 XMLApplicationMarkupLanguage.SeeXAML
WindowsApplicationprojects,119,120 XMLdocumentationfile,134
WindowsCommunicationFoundation.SeeWCF XMLEditor,356,404
WindowsForms,32,219 XMLfiles,134
Windowsmenu,15 XMLforHTML(XHTML),404
WindowsPresentationFramework.SeeWPF XMLmenu,407
WindowsProjects,32–33 XMLserialization,134
WindowsServices,33 XMLTransformation(XSLT),407
Windowsversions,6 XSLT(XMLTransformation),407