Microsoft Visual C# 2010 Step by Step (P12) pot

50 382 0
Microsoft Visual C# 2010 Step by Step (P12) pot

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

520 Part IV Working with Windows Applications Add properties to validate the privilege level and number of tickets 1. Switch to the Code and Text Editor window displaying the TicketOrder.cs file. 2. Add the PrivilegeLevel enumeration shown next in bold type to the file, above the TicketOrder class: enum PrivilegeLevel { Standard, Premium, Executive, PremiumExecutive } class TicketOrder { } You will use this enumeration to specify the type of the PrivilegeLevel property in the TicketOrder class. 3. Add the privilegeLevel and numberOfTickets private fields to the TicketOrder class, as shown in bold type here: class TicketOrder { private string eventName; private string customerReference; private PrivilegeLevel privilegeLevel; private short numberOfTickets; } 4. Add the private checkPrivilegeAndNumberOfTickets Boolean method to the TicketOrder class as shown in bold type here: class TicketOrder { private bool checkPrivilegeAndNumberOfTickets( PrivilegeLevel proposedPrivilegeLevel, short proposedNumberOfTickets) { bool retVal = false; switch (proposedPrivilegeLevel) { case PrivilegeLevel.Standard: retVal = (proposedNumberOfTickets <= 2); break; case PrivilegeLevel.Premium: retVal = (proposedNumberOfTickets <= 4); break; case PrivilegeLevel.Executive: retVal = (proposedNumberOfTickets <= 8); break; Chapter 24 Performing Validation 521 case PrivilegeLevel.PremiumExecutive: retVal = (proposedNumberOfTickets <= 10); break; } return retVal; } } This method examines the values in the proposedPrivilegeLevel and proposedNumberOfTickets parameters and tests them for consistency according to the business rules described earlier in this chapter. If the values are consistent, this method returns true; otherwise, it returns false. 5. Add the public PrivilegeLevel and NumberOfTickets properties shown next in bold type to the TicketOrder class. Note that the type of the PrivilegeLevel property is the PrivilegeLevel enumeration: class Customer { public PrivilegeLevel PrivilegeLevel { get { return this.privilegeLevel; } set { this.privilegeLevel = value; if (!this.checkPrivilegeAndNumberOfTickets(value, this.numberOfTickets)) { throw new ApplicationException( "Privilege level too low for this number of tickets"); } } } public short NumberOfTickets { get { return this.numberOfTickets; } set { this.numberOfTickets = value; if (!this.checkPrivilegeAndNumberOfTickets(this.privilegeLevel, value)) { throw new ApplicationException( "Too many tickets for this privilege level"); } if (this.numberOfTickets <=0) { throw new ApplicationException( "You must buy at least one ticket"); } } } } 522 Part IV Working with Windows Applications The set accessors of these properties call the CheckPrivilegeAndNumberOfTickets method to verify that the privilegeLevel and the numberOfTickets fields match, and they raise an exception if the fields do not match. Additionally, the set accessor for the NumberOfTickets property verifies that the user has specified at least one ticket. You do not need to verify that the user has specified a value for the PrivilegeLevel property because it defaults to Standard (the first item in the PrivilegeLevel enumeration). 6. Add the ToString method shown next in bold type to the TicketOrder class: class TicketOrder { public override string ToString() { string formattedString = String.Format("Event: {0}\tCustomer: {1}\tPrivilege: {2}\tTickets: {3}", this.eventName, this.customerReference, this.privilegeLevel.ToString(), this.numberOfTickets.ToString()); return formattedString; } } You will use this method to display the details of ticket orders to verify that the data is correct. The next step is to bind the privilegeLevel combo box and the numberOfTickets slider control on the form to these new properties. However, if you stop and think for a moment, you will realize that there is a small problem with the PrivilegeLevel property. You need to bind the Text property of the privilegeLevel combo box to the PrivilegeLevel property of the TicketOrder object created by the form. The type of the Text property is string. The type of the PrivilegeLevel property is PrivilegeLevel (an enumeration). You must convert between string and PrivilegeLevel values for the binding to work. Fortunately, with the binding mecha- nism implemented by WPF, you can specify a converter class to perform actions such as this. Note A WPF binding can automatically convert between an enumeration and a string if the string values are identical to the names of each element in the enumeration. In the Ticket Order application, the first three items in the privilegeLevel combo box (Standard, Premium, and Executive) correspond directly to elements with the same names in the PrivilegeLevel enumera- tion. However, the final item in the combo box is Premium Executive (with a space), but the cor- responding element in the enumeration is called PremiumExecutive (without a space). The WPF binding cannot convert between these two values, so a converter class is required. Converter methods reside in their own classes that must implement the IValueConverter interface. This interface defines two methods: Convert, which converts from the type used by the property in the class that is providing the data for the binding to the type displayed on Chapter 24 Performing Validation 523 the form, and ConvertBack, which converts the data from the type displayed on the form to the type required by the class. Create the converter class and methods 1. In the TicketOrder.cs file, add the following using statement to the list at the top of the file: using System.Windows.Data; The IValueConverter interface is defined in this namespace. 2. Add the PrivilegeLevelConverter class shown next to the end of the file, after the Customer class: [ValueConversion(typeof(string), typeof(PrivilegeLevel))] public class PrivilegeLevelConverter : IValueConverter { } The text in brackets directly above the class is an example of an attribute. An attribute provides descriptive metadata for a class. The ValueConversion attribute is used by tools such as the WPF designer in the Design View window to verify that you are apply- ing the class correctly when you reference it. The parameters to the ValueConversion attribute specify the type of the value displayed by the form (string) and the type of the value in the corresponding property in the class (PrivilegeLevel). You will see more examples of attributes in later chapters in this book. 3. In the PrivilegeLevelConverter class, add the Convert method shown here in bold type: [ValueConversion(typeof(string), typeof(PrivilegeLevel))] public class PrivilegeLevelConverter: IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { PrivilegeLevel privilegeLevel = (PrivilegeLevel)value; string convertedPrivilegeLevel = String.Empty; switch (privilegeLevel) { case PrivilegeLevel.Standard: convertedPrivilegeLevel = "Standard"; break; case PrivilegeLevel.Premium: convertedPrivilegeLevel = "Premium"; break; case PrivilegeLevel.Executive: convertedPrivilegeLevel = "Executive"; break; 524 Part IV Working with Windows Applications case PrivilegeLevel.PremiumExecutive: convertedPrivilegeLevel = "Premium Executive"; break; } return convertedPrivilegeLevel; } } The signature of the Convert method is defined by the IValueConverter interface. The value parameter is the value in the class that you are converting from. (You can ignore the other parameters for now.) The return value from this method is the data bound to the property on the form. In this case, the Convert method converts a PrivilegeLevel value to a string. Notice that the value parameter is passed in as an object, so you need to cast it to the appropriate type before attempting to use it. 4. Add the ConvertBack method shown next in bold type to the PrivilegeLevelConverter class: [ValueConversion(typeof(string), typeof(PrivilegeLevel))] public class PrivilegeLevelConverter: IValueConverter { public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { PrivilegeLevel privilegeLevel = PrivilegeLevel.Standard; switch ((string)value) { case "Standard": privilegeLevel = PrivilegeLevel.Standard; break; case "Premium": privilegeLevel = PrivilegeLevel.Premium; break; case "Executive": privilegeLevel = PrivilegeLevel.Executive; break; case "Premium Executive": privilegeLevel = PrivilegeLevel.PremiumExecutive; break; } return privilegeLevel; } } The ConvertBack method is also part of the IValueConverter interface. In the ConvertBack method, the value parameter is now the value from the form that you Chapter 24 Performing Validation 525 are converting back to a value of the appropriate type for the class. In this case, the ConvertBack method converts the data from a string (displayed in the Text property in the combo box) to the corresponding Title value. 5. On the Build menu, click Build Solution. Verify that the solution compiles correctly, and correct any errors and rebuild the solution if necessary. Bind the combo box and slider controls on the form to the properties in the TicketOrder class 1. Return to the Design View window displaying the TicketForm.xaml file. 2. In the XAML pane, add a PrivilegeLevelConverter object as a resource to the window, and specify a key value of privilegeLevelConverter, as shown in bold type here: <Window.Resources> <ticketOrder:TicketOrder x:Key="orderData" /> <ticketOrder:PrivilegeLevelConverter x:Key="privilegeLevelConverter" /> </Window.Resources> 3. Locate the definition of the privilegeLevel combo box control, and style the control by using the errorStyle style. After the list of combo box items, add the XAML code shown next in bold type to bind the Text property of the combo box to the Title property in the orderData object, specifying the titleConverter resource as the object providing the converter methods: <ComboBox Style="{StaticResource errorStyle}" Name="privilegeLevel" > <ComboBox.Text> <Binding Source="{StaticResource orderData}" Path="PrivilegeLevel" Converter="{StaticResource privilegeLevelConverter}" > <Binding.ValidationRules> <ExceptionValidationRule /> </Binding.ValidationRules> </Binding> </ComboBox.Text> <ComboBox.Items> </ComboBox.Items> </ComboBox> 4. Modify the definition for the numberOfTickets slider control .Apply the errorStyle style, and bind the Value property to the NumberOfTickets property of the orderData object, as shown here in bold type: <Slider Style="{StaticResource errorStyle}" Height="22" HorizontalAlignment="Left" Margin="156,171,0,0", Name="numberOfTickets" VerticalAlignment="Top" Width="205" SmallChange="1" TickPlacement="BottomRight" Maximum="10" IsSnapToTickEnabled="True" > <Slider.Value> <Binding Source="{StaticResource orderData}" Path="NumberOfTickets"> <Binding.ValidationRules> 526 Part IV Working with Windows Applications <ExceptionValidationRule /> </Binding.ValidationRules> </Binding> </Slider.Value> </Slider> 5. On the View menu, click Code to switch to the Code and Text Editor window displaying the TicketForm.xaml.cs file. 6. Change the code in the purchaseTickets_Click method, as shown here in bold type: private void purchaseTickets_Click(object sender, RoutedEventArgs e) { Binding ticketOrderBinding = BindingOperations.GetBinding(privilegeLevel, ComboBox.TextProperty); TicketOrder ticketOrder = ticketOrderBinding.Source as TicketOrder; MessageBox.Show(ticketOrder.ToString(), "Purchased"); } This code displays the details of the order in the message box. (It still does not actually save the ticket order anywhere.) The static GetBinding method of the BindingOperations class returns a reference to the object to which the specified property is bound. In this case, the GetBinding method retrieves the object bound to the Text property of the title combo box. This should be the same object referred to by the orderData resource. In fact, the code could have queried any of the bound properties of the eventList, custom- erReference, privilegeLevel, or numberOfTickets controls to retrieve the same reference. The reference is returned as a Binding object. The code then casts this Binding object into a TicketOrder object before displaying its details. You can now run the application again and see how the validation performs. Run the application, and test the validation 1. On the Debug menu, click Start Without Debugging to build and run the application. 2. In the Privilege Level combo box, click Premium. 3. Set the Tickets slider to 5. The CheckPrivilegeAndNumberOfTickets method in the TicketOrder class generates an exception because the privilege level and the number of tickets do not match. The Tickets slider is highlighted with a red border. Rest the mouse pointer on the Tickets slider, and verify that the ScreenTip text “Too many tickets for this privilege level” appears. 4. In the Privilege Level combo box, click Executive. Although the privilege level is now sufficient to enable the customer to order 5 tickets, the slider remains highlighted. 5. Set the Tickets slider to 6. Chapter 24 Performing Validation 527 Verify that the red highlighting disappears. The validation occurs only when you change the value in a control, not when you change the value of a different control. 6. In the Privilege Level combo box, click Standard. The combo box is highlighted. If you hover the mouse cursor over the combo box, it should display the message “Privilege level too low for this number of tickets.” 7. Set the Tickets slider to 5. The slider control is now also highlighted. 8. On the File menu, click Purchase. A message box appears, displaying the privilege level (Standard) and the number of tickets (5) for the order. Additionally, the event and customer reference are both blank. Although the form contains erroneous and missing data, you can still make the purchase! 9. Click OK, and then type C1234 in the customerReference text box, but do not click away from this text box. 10. On the File menu, click Purchase again. The message box does not include the customer reference. This happens because the customerReference text box on the form has not lost the focus. Remember from earlier that data binding validation for a text box occurs only when the user clicks another control on the form. The same applies to the data itself; by default, it is copied to the orderDetails object only when the text box loses the focus. In fact, it is the act of copy- ing the data from the form to the orderDetails object that triggers the validation. 11. Click OK, and then click the Event combo box and select Little Mudford Festival. 12. On the File menu, click Purchase. This time, the message box displays all the details from the form. 13. Click OK, close the application, and return to Visual Studio 2010. You can see from this exercise that although the validation successfully cross-checks the Privilege Level and Tickets controls, there is still more work to be done before the application is usable. Changing the Point at Which Validation Occurs The issues with the application are that the validation is performed at the wrong time, is in- consistently applied, and does not actually prevent the user from providing inconsistent data. You just need an alternative approach to handling the validation. The solution is to check the user’s input only when the user attempts to make the purchase. This way, you can ensure the user has finished entering all the data and that it is consistent. If there are any problems, 528 Part IV Working with Windows Applications you can display an error message and prevent the data from being used until the problems have been corrected. In the following exercise, you will modify the application to postpone validation until the user attempts to purchase tickets. Validate data explicitly 1. Return to the Design View window displaying TicketForm.xaml. In the XAML pane, modify the binding for the privilegeLevel combo box and set the UpdateSourceTrigger property to “Explicit”, as shown in bold type here: <ComboBox Name="privilegeLevel" > <ComboBox.Text> <Binding Source="{StaticResource orderData}" Path="PrivilegeLevel" Converter="{StaticResource privilegeLevelConverter}" UpdateSourceTrigger="Explicit" > </Binding> </ComboBox.Text> </ComboBox> The UpdateSourceTrigger property governs when the information entered by the user is sent back to the underlying TicketOrder object and validated. Setting this property to “Explicit” postpones this synchronization until your application explicitly performs it by using code. 2. Modify the bindings for the eventList, customerReference, and numberOfTickets controls to set the UpdateSourceTrigger property to “Explicit”: <ComboBox Name="eventList" > <ComboBox.Text> <Binding Source="{StaticResource orderData}" Path="EventName" UpdateSourceTrigger="Explicit" > </Binding> </ComboBox.Text> </ComboBox> <TextBox Name="customerReference" > <TextBox.Text> <Binding Source="{StaticResource orderData}" Path="CustomerReference" UpdateSourceTrigger="Explicit" > </Binding> </TextBox.Text> </TextBox> <Slider Name="numberOfTickets" > <Slider.Value> <Binding Source="{StaticResource orderData}" Path="NumberOfTickets" UpdateSourceTrigger="Explicit" > Chapter 24 Performing Validation 529 </Binding> </Slider.Value> </Slider> 3. Display the TicketForm.xaml.cs file in the Code and Text Editor window. In the purchaseTickets_Click method, add the statements shown next in bold type to the start of the method: private void purchaseTickets_Click(object sender, RoutedEventArgs e) { BindingExpression eventBe = eventList.GetBindingExpression(ComboBox.TextProperty); BindingExpression customerReferenceBe = customerReference.GetBindingExpression(TextBox.TextProperty); BindingExpression privilegeLevelBe = privilegeLevel.GetBindingExpression(ComboBox.TextProperty); BindingExpression numberOfTicketsBe = numberOfTickets.GetBindingExpression(Slider.ValueProperty); } These statements create BindingExpression objects for each of the four controls with binding validation rules. You will use these objects in the next step to propagate the values on the form to the TicketOrder object and trigger the validation rules. 4. Add the statements shown next in bold type to the purchaseTickets_Click method after the code you added in the preceding step: private void purchaseTickets_Click(object sender, RoutedEventArgs e) { eventBe.UpdateSource(); customerReferenceBe.UpdateSource(); privilegeLevelBe.UpdateSource(); numberOfTicketsBe.UpdateSource(); } The UpdateSource method of the BindingExpression class synchronizes data in an object with the controls that reference the object through bindings. It sends the values in the bound properties of controls on the form back to the TicketOrder object. When this oc- curs, the data is also validated. The statements you added in the step update the properties in the TicketOrder object with the values entered by the user on the form, and they validate the data as they do so. The BindingExpression class provides a property called HasError that indicates whether the UpdateSource method was successful or whether it caused an exception. [...]... customer Connect to the database 1 Start Visual Studio 2010 if it is not already running 2 Create a new project called ReportOrders by using the Console Application template Save it in the \Microsoft Press \Visual CSharp Step By Step\ Chapter 25 folder under your Documents folder Chapter 25  Querying Information in a Database 539 Note  Remember, if you are using Visual C# 2010 Express, you can specify the... rather than that of an administrator 10 In the command prompt window, type the following command to go to the \Microsoft Press \Visual CSharp Step By Step\ Chapter 25 folder under your Documents folder Replace Name with your user name cd "\Users\Name\Documents \Microsoft Press \Visual CSharp Step By Step\ Chapter 25" 11 In the command prompt window, type the following command: sqlcmd -S.\SQLExpress -E -iinstnwnd.sql... Examine the HasError property of each BindingExpression object If this property is true, the validation failed Microsoft Visual C# 2010 Step by Step Part V Managing Data In this part: Querying Information in a Database 535 Displaying and Editing Data by Using the Entity Framework  and Data Binding 565 533 Chapter... Server 2008 Express This software is available on the retail DVD with Microsoft Visual Studio 2010 and Visual C# 2010 Express and is installed by default Important  It is recommended that you use an account that has Administrator privileges to perform the exercises in this chapter and the remainder of this book Querying a Database by Using ADO.NET The ADO.NET class library contains a comprehensive framework... book, “Building Windows Presentation Foundation Applications,” you learned how to use Microsoft Visual C# to build user interfaces and present and validate information In Part V, you will learn about managing data by using the data access functionality available in Microsoft Visual Studio 2010 and the Microsoft NET Framework The chapters in this part of the book describe ADO.NET, a library of objects... return to Visual Studio In this chapter, you saw how to perform basic validation by using the default exception v ­ alidation rule processing provided by using data binding You learned how to define your own custom validation rules if you want to perform more complex checks n If you want to continue to the next chapter Keep Visual Studio 2010 running, and turn to Chapter 25 n If you want to exit Visual. .. Microsoft SQL Server database by using Microsoft ADO.NET n Define entity classes for holding data retrieved from a database n Use LINQ to SQL to query a database and populate instances of entity classes n Create a custom DataContext class for accessing a database in a typesafe manner In Part IV of this book, “Building Windows Presentation Foundation Applications,” you learned how to use Microsoft Visual. .. to Visual Studio 2010 Chapter 25  Querying Information in a Database 549 Querying a Database by Using LINQ to SQL In Chapter 20, “Querying In-Memory Data by Using Query Expressions,” you saw how to use LINQ to examine the contents of enumerable collections held in memory LINQ provides query expressions, which use SQL-like syntax for performing queries and generating a result set that you can then step. .. null variable in C#: it doesn’t have a value, but if you try to read it, you get an error In the Orders table, the ShippedDate column can contain a null value if the order has not yet been shipped You should also note that this is a SqlNullValueException and consequently is not caught by the SqlException handler 6 Press Enter to close the console window and return to Visual Studio 2010 Closing Connections... ConnectionString property of the SqlConnection object, which you will use in the next step You can also encode many other elements in the connection string by using the SqlConnectionStringBuilder class—the properties shown in this example are a minimal but sufficient set See the documentation supplied with Visual Studio 2010 for more details 8 Add the following statement shown in bold to the code in the . have installed Microsoft SQL Server 2008 Express. This software is available on the retail DVD with Microsoft Visual Studio 2010 and Visual C# 2010 Express and is installed by default. Important. the Microsoft Press Visual CSharp Step By Step Chapter 25 folder under your Documents folder. Replace Name with your user name. cd "UsersNameDocuments Microsoft Press Visual CSharp Step. each BindingExpression object. If this property is true, the validation failed. Microsoft Visual C# 2010 Step by Step 533 Part V Managing Data In this part: Querying Information in a Database

Ngày đăng: 05/07/2014, 16:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan