1. Trang chủ
  2. » Công Nghệ Thông Tin

Professional Visual Basic 2010 and .neT 4 phần 6 ppt

133 294 0

Đ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

Thông tin cơ bản

Định dạng
Số trang 133
Dung lượng 4,21 MB

Nội dung

622 ❘ CHAPTER 17 wPF dEsktoP aPPliCatioNs Don’t worry about being exactly on 40, because after you’ve selected your two points you are going to switch to the XAML view. Now, instead of the previous display, you have code similar to what appears here: <Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ProVB_WPF" Height="350" Width="525" Name="MainWindow"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="45" /> <RowDefinition Height="215*" /> <RowDefinition Height="40" /> </Grid.RowDefinitions> </Grid> </Window> Code snippet from MainWindow.xaml Note if instead of working along with the text you are looking at the sample download, keep in mind that the download includes all of the changes that will be made during the creation of this first step. The preceding snippet includes a few edits that you can reproduce at this point. Note that the title of the window has been modified to match the project name. The XAML now includes a new section related to the Grid.RowDefinitions. This section contains the specification of sections within the points in the grid. When you selected those points in the designer, you were defining these sections. The default syntax associated with the height of each section is the number of pixels followed by an asterisk. The asterisk indicates that when the window is resized, this row should also resize. For this application, only the center section should resize, so the asterisk has been removed from the top and bottom row definitions. This provides a set of defined regions that can be used to align controls within this form. Thus, the next step is to add some controls to the form and create a basic user interface. In this scenario, the actions should be very familiar to any developer who has worked with either Windows Forms or ASP.NET forms. Controls WPF provides an entirely different set of libraries for developing applications. However, although these controls exist in a different library, how you interact with them from Visual Basic is generally the same. Each control has a set of properties, events, and methods that you can leverage. The XAML file may assign these values in the declarative format of XML, but you can still reference the same properties on the instances of the objects that the framework creates within your Visual Basic code. Starting with the topmost section of the grid, Grid.Row 0, drag the following controls from the Toolbox onto the form: a Label, a TextBox, and a Button. These can be aligned into this region in the same order they were added. Ensure that the label is bound to the left side and top of the window, while the button is bound to the right side and top of the window. Meanwhile, the text box should be bound to the top and both sides of the window so that as the window is stretched, the width of the text box increases. The resulting XAML should be similar to this: <Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ProVB_WPF" Height="350" Width="525" Name="MainWindow"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="45" /> <RowDefinition Height="215*" /> <RowDefinition Height="40" /> </Grid.RowDefinitions> Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com <Label Margin="0,11,0,0" Name="Label1" HorizontalAlignment="Left" Width="80" Height="23" VerticalAlignment="Top">Image Path:</Label> <TextBox Margin="81,13,92,0" Name="TextBox1" Height="21" VerticalAlignment="Top" /> <Button HorizontalAlignment="Right" Margin="0,11,9,11" Name="ButtonBrowse" Width="75">Images . . .</Button> </Grid> </Window> Code snippet from MainWindow.xaml As shown in the newly added lines (in bold), each control is assigned a name and defines a set of editable properties. Note that these names can be addressed from within the code and that you can handle events from each control based on that control’s named instance. For now, however, just adjust the text within the label to indicate that the text box to its immediate right will contain a folder path for images, and adjust the button control. Rename the Button control to ButtonBrowse and use the text Images to label the button. There is obviously more to do with this button, but for now you can finish creating the initial user interface. Next, add the following controls in the following order. First, add an Image control. To achieve a design surface similar to the one shown in Figure 17-2, drop the Image control so that it overlaps both the middle and bottom sections of the grid display. Now add three buttons to the bottom portion of the display. At this point the controls can be aligned. You can do this through a combination of editing the XAML directly and positioning things on the screen. For example, expand the Image control to the limits of the two bottom grid rows using the design surface; similarly, align the buttons visually on the design surface. FIGURE 172 Creating a WPF Application ❘ 623 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 624 ❘ CHAPTER 17 wPF dEsktoP aPPliCatioNs As shown in the figure, the separations for the two row definitions are described in the design surface, and each of the buttons has a custom label. Note that the Next button is followed by a pair of greater than symbols, but the Prev button is missing a matching set of less than symbols. They could have been added as the &lt symbol but instead one of the changes to be made in the Visual Basic code is the addition of these symbols to the button label. First, however, review the XAML code and ensure that, for example, the Image control is assigned to Grid .Row 1 and that the property Grid.RowSpan is 2. Unlike the items that were in Grid.Row 0, the items in other rows of the grid must be explicitly assigned. Similarly, the name and caption of each button in the bottom row of the grid are modified to reflect that control’s behavior. These and similar changes are shown in the following XAML: <Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ProVB_WPF" Height="350" Width="525" Name="MainWindow"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="45" /> <RowDefinition Height="215*" /> <RowDefinition Height="40" /> </Grid.RowDefinitions> <Label Margin="0,11,0,0" Name="Label1" HorizontalAlignment="Left" Width="80" Height="23" VerticalAlignment="Top">Image Path:</Label> <TextBox Margin="81,13,92,0" Name="TextBox1" Height="21" VerticalAlignment="Top" /> <Button HorizontalAlignment="Right" Margin="0,11,9,11" Name="ButtonBrowse" Width="75">Images . . .</Button> <Image Grid.Row="1" Grid.RowSpan="2" Margin="0,0,0,0" Name="Image1" Stretch="Fill" /> <Button Grid.Row="2" HorizontalAlignment="Right" Margin="0,0,15,8" Name="ButtonNext" Width="75" Height="23" VerticalAlignment="Bottom">Next >> </Button> <Button Grid.Row="2" HorizontalAlignment="Left" Margin="15,0,0,8" Name="ButtonPrev" Width="75" Height="23" VerticalAlignment="Bottom"> Prev</Button> <Button Grid.Row="2" Margin="150,0,150,8" Name="ButtonLoad" Height="23" VerticalAlignment="Bottom">View Images</Button> </Grid> </Window> Code snippet from MainWindow.xaml Note in the bold sections the description of the new controls. The Image control is first, and it is positioned in Grid.Row number 1, which, because .NET arrays are always zero-based, is the second row. The second attribute on this node indicates that it will span more then a single row in the grid. For now, this control uses the default name, and it has been set so that it will stretch to fill the area that contains it. Following the Image control are the definitions for the three buttons along the bottom of the display. For now, these buttons will control the loading of images; over the course of this chapter, these buttons will be either removed or redone significantly. The order of these buttons isn’t important, so following their order in the file, the first button is like the others positioned in the final row of the grid. This button has been placed on the right-hand side of this area and is bound to the bottom and right corners of the display. Its name has been changed to “ButtonNext” and its label is “Next >>.” Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com The next button is the Prev button, which has been placed and bound to the left - hand side and bottom of the display. Its name has been changed to “ ButtonPrev, ” and its display text has been changed to read “ Prev. ” As noted earlier, the arrow symbols are not in the button name; and, as you can test in your own code, attempting to add them here causes an error. Finally, there is the ButtonLoad button, which is centered in the display area. It has been bound to both sides of the display to maintain its position in the center. The label for this button is “ View Images, ” which is, of course, the goal of this application. However, in order for that to happen, you need an event handler for this button; in fact, you need several event handlers in order to get the basic behavior of the application in place. Event Handlers In previous versions of Visual Studio you could click on a control and Visual Studio would automatically generate the default event handler for that control in your code. Fortunately, WPF also provides this behavior, so generate the following event handlers: Double - click on the title bar of the form to generate the ➤ MainWindow_Loaded event handler. Double - click on the Images button to create the ➤ ButtonBrowse_Click h a n d l e r . Double - click on the Load button to create the ➤ ButtonLoad_Click h a n d l e r . Double - click on the Prev button to create the ➤ ButtonPrev_Click h a n d l e r . Double - click on the Next button to create the ➤ ButtonNext_Click h a n d l e r . To create each of these handlers, you need to return to the Design view and click on the associated control, but after they are created you can stay in Code view for most of this section. Take a look at the ButtonBrowse_Click event handler ’ s method stub: Private Sub ButtonBrowse_Click(ByVal sender As System.Object, _ ByVal e As System.Windows.RoutedEventArgs) _ Handles ButtonBrowse.Click End Sub The preceding code was reformatted with line extension characters to improve readability, but this is essentially what each of your event handlers looks like. As a Visual Basic developer, you should fi nd this syntax very familiar. Note that the method name has been generated based on the control name and the event being handled. The parameter list is generated with the “ sender ” and e parameter values, although the e value now references a different object in the System.Windows namespace. Finally, defi ned here is the V B - s p e c i fi c Handles syntax that indicates this method is an event handler, and which specifi c event or events it handles. While this is a very familiar, powerful, and even recommended way of defi ning event handlers with VB and WPF, it isn ’ t the only way. WPF allows you to defi ne event handlers within your XAML code. To be honest, if this were a book on C#, we would probably spend a fair amount of time covering the advantages of that type of event handler declaration. After all, C# doesn ’ t support the direct association of the event handler declaration with the method handling the event; as a result, C# developers prefer to declare their event handlers in XAML. However, one of the goals of XAML is the separation of the application logic from the UI, and placing the names of event handlers in the UI actually couples the UI to the application logic. It shouldn ’ t matter to the UI whether the Click event or the DoubleClick or any other event is being handled by custom logic. Therefore, although this section introduces the way to defi ne events directly in XAML, the recommendation is to defi ne event handlers with the code that implements the handler. Visual Basic provides a default implementation of WPF that encourages less coupling of the UI to the application code than C# does. Creating a WPF Application ❘ 625 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 626 ❘ CHAPTER 17 wPF dEsktoP aPPliCatioNs In order to demonstrate this in the code, return to the Design view for your form. Select the Images button and position your cursor just after the word Button, which names this node. Press the spacebar. You’ll see that you have IntelliSense, indicating which properties and events are available on this control. Typing a c adjusts the IntelliSense display so that you see the Click event. Select this event by pressing Tab and you’ll see the display shown in Figure 17-3. FIGURE 173 As shown here, not only does the XAML editor support full IntelliSense for selecting properties and events on a control, when an event is selected, it displays a list of possible methods that can handle this event. Of particular note is the first item in the list, which enables you to request that a new event handler be created in your code. Selecting this item tells Visual Studio to generate the same event handler stub that you created by double-clicking on the control; however, instead of placing the Handles clause on this method, the definition of this method as an event handler is kept in the XAML. This causes two issues. First, if you are looking only at the code, then nothing explicitly indicates whether a given method in your code is in fact an event handler. This makes maintaining the code a bit (not a lot) more difficult to maintain. Second, if you have handled an event that is specific to Windows as opposed to the Web, then your XAML won’t be portable. Neither of these side effects is desirable. Thus, given the VB syntax for defining events as part of the method declaration, the code in this chapter avoids the embedded XAML style of declaring standard Windows event handlers. At this point, you could run your application. It won’t do anything except allow you to close it, but you can verify that it behaves as expected and save your work. Adding Behavior It’s almost time to make this UI do something, but there is one more step before you start working with code. As part of this application, you want to allow users to select the directory from which images should be displayed. In theory, you could (and in practice, at some time probably would) write a custom interface Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com for selecting or navigating to the images directory. However, for this application that isn’t important, and you want a quick and easy solution. Unfortunately, WPF doesn’t offer any native control that supports providing a quick and easy view into the file system. However, Windows Forms does, and in this case you want to leverage this control. The good news is that you can, and the even better news is that you don’t need the Windows interop library in order to do so. Because something like the Browse Folders dialog isn’t a control hosted on your form, you can reference it from your code. Thus, although you need the Windows Forms Integration Library and the WindowsFormsHost control discussed in Chapter 16 for any UI-based controls, in this case the code just needs to reference the System.Windows.Forms library. Because the System.Windows.Forms library isn’t automatically included as a reference in a WPF application, you need to manually add a reference to this library. Keep in mind that this library isn’t going to be available to you outside of WPF’s rich client implementation. Thus, this feature is limited to WPF running on the client; for other scenarios you would change out how you select an image. Open the My Project display and select the References tab. Click the Add button to open the Add Reference dialog and then select the System .Windows.Forms library, as shown in Figure 17-4. You can’t add controls to your WPF form without leveraging the Windows.Forms.Integration library, but you can, behind the scenes, continue to reference controls and features of Windows Forms. With this additional reference, you can begin to place some code into this application. Start with the window_loaded event. This event is where you’ll define the default path for the image library, set up the label for the Prev button, and change the default property of the grid control so that it handles the images the way you want: Private Sub MainWindow_Loaded(ByVal sender As System.Object, _ ByVal e As System.Windows.RoutedEventArgs) _ Handles MyBase.Loaded ' Append the << to the text for the button since these are _ ' reserved characters within XAML ButtonPrev.Content = "<< " + ButtonPrev.Content.ToString() ' Set the default path from which to load images TextBox1.Text = _ Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) ' Have the images maintain their aspect ration Image1.Stretch = Stretch.Uniform End Sub Code snippet from MainWindow.vb The preceding implementation handles these three tasks. It takes the content of the ButtonPrev control and appends the two less than symbols to the front of the string so that both buttons are displayed uniformly. Of course, long term, this code is going to be disposed of, but for now it helps to illustrate that while controls such as Button may seem familiar from Windows Forms, these controls are in fact different. The WPF version of the Button control doesn’t have a text property; it has a content property. The content property is, in fact, an untyped object reference. In the case of this application, you know this content is a string to which you can append additional text. However, this code is neither a good idea nor easily maintained, so this is just a temporary solution. FIGURE 174 Creating a WPF Application ❘ 627 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 628 ❘ CHAPTER 17 wPF dEsktoP aPPliCatioNs Next, the code updates the text property of the TextBox control used on the form. This text box displays the folder for the images to display. In order to provide a dynamic path, the code leverages the Environment class to get a folder path. To this shared method the code passes a shared environment variable: Environment.SpecialFolder.MyPictures. This variable provides the path to the current user’s My Pictures folder (or the User’s Pictures folder on Windows 7 and Vista). By using this value, the code automatically points to a directory where the current user would be expected to have images. Finally, to again demonstrate that any of the WPF classes can be modified within your code, this code sets a property on the Image control. Specifically, it updates the Stretch property of the Image control to ensure that images are resized with their aspect maintained. Thus, if an image is square, then when your image control becomes a rectangle, the image remains square. The Stretch.Uniform value indicates that the aspect should be maintained, while other members of the Windows.Stretch enumeration provide alternative behavior. The next step is to implement your first button handler, the ButtonBrowse_Click handler. When this button is clicked, the application should open the Folder Browse dialog, displaying the currently selected folder as the default. The user should be allowed to navigate to an existing folder or create a new folder. When the dialog is closed, the application should, if the user selected a new folder, update the folder’s text box to display this new location: Private Sub ButtonBrowse_Click(ByVal sender As System.Object, _ ByVal e As System.Windows.RoutedEventArgs) _ Handles ButtonBrowse.Click Dim folderDialog As System.Windows.Forms.FolderBrowserDialog = _ New System.Windows.Forms.FolderBrowserDialog() folderDialog.Description = "Select the folder for images." folderDialog.SelectedPath = TextBox1.Text Dim res As System.Windows.Forms.DialogResult = _ folderDialog.ShowDialog() If res = System.Windows.Forms.DialogResult.OK Then TextBox1.Text = folderDialog.SelectedPath End If End Sub Code snippet from MainWindow.vb The preceding code block declares an instance of the System.Windows.Forms.FolderBrowserDialog control. As noted when the reference was added, this control isn’t part of your primary window display, so you can create an instance of this dialog without needing the Windows.Forms.Interface library. It then sets a description, indicating to users what they should do while in the dialog, and updates the current path for the dialog to reflect the currently selected folder. The dialog is then opened and the result assigned directly into the variable res. This variable is of type System.Windows.Forms.DialogResult and is checked to determine whether the user selected the OK button or the Cancel button. If OK was selected, then the currently selected folder is updated. Now it’s time to start working with the images. That means you need to retrieve a list of images and manipulate that list as the user moves forward and backward through it. You could constantly return to the source directory to find the next and previous images, but you will get much better performance by capturing the list locally and keeping your current location in the list. This implies two local variables; and because you want these variables available across different events, you need to declare them as member variables to your class: Class MainWindow Private m_imageList As String() = {} Private m_curIndex As Integer = 0 Private Sub MainWindow_Loaded(ByVal sender As System.Object, _ ByVal e As System.Windows.RoutedEventArgs) _ Handles MyBase.Loaded ' Append the << to the text for the button since these are _ ' reserved characters within XAML ButtonPrev.Content = "<< " + ButtonPrev.Content.ToString() Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com ' Set the default path from which to load images TextBox1.Text = _ Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) ' Have the images maintain their aspect ration Image1.Stretch = Stretch.Uniform End Sub Private Sub ButtonBrowse_Click(ByVal sender As System.Object, _ ByVal e As System.Windows.RoutedEventArgs) _ Handles ButtonBrowse.Click Dim folderDialog As System.Windows.Forms.FolderBrowserDialog = _ New System.Windows.Forms.FolderBrowserDialog() folderDialog.Description = "Select the folder for images." folderDialog.SelectedPath = TextBox1.Text Dim res As System.Windows.Forms.DialogResult = _ folderDialog.ShowDialog() If res = System.Windows.Forms.DialogResult.OK Then TextBox1.Text = folderDialog.SelectedPath End If End Sub Private Sub ButtonLoad_Click(ByVal sender As System.Object, _ ByVal e As System.Windows.RoutedEventArgs) _ Handles ButtonLoad.Click Image1.Source = Nothing m_imageList = System.IO.Directory.GetFiles(TextBox1.Text, "*.jpg") m_curIndex = 0 If m_imageList.Count > 0 Then Image1.Source = _ New System.Windows.Media.Imaging.BitmapImage( _ New System.Uri(m_imageList(m_curIndex))) End If End Sub Code snippet from MainWindow.vb The beginning of the preceding code adds two new properties to the class MainWindow. Both values are private variables that have not been exposed as public properties. They are being made available for use in the image-handling buttons. Your code should look similar to the preceding code. The second bold section is an implementation of the ButtonLoad Click event handler. This event handler is called when the user clicks the button, ButtonLoad, and the first thing it does is clear the current image from the display. It then leverages the System.IO.Directory class, calling the shared method GetFiles to retrieve a list of files. For simplicity, this call screens out all files that don’t have the extension .jpg. In a full production application, this call would probably use a much more complex screening system to gather all types of images and potentially feed a folder navigation control so that users could change the selected folder or even add multiple folders at once. Once the list of files is retrieved and assigned to the private variable m_imageList, the code clears the current index and determines whether any files were returned for the current directory. The screenshots in this chapter have three images in the folder in order to obtain a small array; however, if no images are present, then the code exists without displaying anything. Here, presume an image is available. The code uses the System.Windows.Media.Imaging class to load an image file as a bitmap. It does this by accepting the URI or path to that image, a path that was returned as an array from your call to GetFiles. Note that the BitmapImage call doesn’t need an image formatted as a bitmap, but instead converts the chosen image to a bitmap format that can then be directly referenced by the source property of the Image control: Private Sub ButtonPrev_Click(ByVal sender As System.Object, _ ByVal e As System.Windows.RoutedEventArgs) _ Handles ButtonPrev.Click If m_imageList.Count > 0 Then m_curIndex -= 1 If m_curIndex < 0 Then m_curIndex = m_imageList.Count - 1 Creating a WPF Application ❘ 629 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 630 ❘ CHAPTER 17 wPF dEsktoP aPPliCatioNs End If Image1.Source = New System.Windows.Media.Imaging.BitmapImage( _ New System.Uri(m_imageList(m_curIndex))) End If End Sub Private Sub ButtonNext_Click(ByVal sender As System.Object, _ ByVal e As System.Windows.RoutedEventArgs) _ Handles ButtonNext.Click If m_imageList.Count > 0 Then m_curIndex += 1 If m_curIndex > m_imageList.Count - 1 Then m_curIndex = 0 End If Image1.Source = New System.Windows.Media.Imaging.BitmapImage( _ New System.Uri(m_imageList(m_curIndex))) End If End Sub End Class Code snippet from MainWindow.vb After the code to load an image has been added, implementing the ButtonPrev and ButtonNext event handlers is fairly simple. In both cases the code first checks to ensure that one or more images are available in the m_imageList. If so, then the code either decrements or increments the m_curIndex value, indicating the image that should currently be displayed. In each case the code ensures that the new index value is within the limits of the array. For example, if it is below 0, then it is reset to the last image index; and if it is greater than the last used index, the counter is reset to 0 to return it to the start of the list. The next logical step is to run the application. If you have images loaded in your Pictures folder, then you can open the first of these images in the application. If not, then you can navigate to another directory such as the Samples folder using the Images button. At this point, you’ll probably agree that the sample application shown in Figure 17-5 looks just like a typical Windows Forms application — so much so in fact that the next steps are included to ensure that this doesn’t look like a Windows Forms application. However, before adding new features, there is a possibility that when you loaded your image, your application didn’t display the image quite like the one shown in Figure 17-5; in fact, it might look more like Figure 17-6. If, when you worked on your own code, you added the Image control after adding the View, Prev, and Next buttons, then your buttons — in particular, the View Images button — might be completely FIGURE 175 FIGURE 176 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com hidden from view. This is caused by the way in which WPF layers and loads controls, and to resolve it you need to change the order in which the controls are loaded in your XAML. Before doing that, however, this is a good place to discuss layers and the WPF layering and layout model. Layout WPF supports a very robust model for control layout, which it achieves by leveraging the capability to layer controls and by providing a set of controls directly related to layout. Combined with the capability to define a reasonable set of layout information for each control, what you wind up with is an adaptable environment that can, at the extreme, provide unique behavior. How does the process work? Within each control are the basic elements associated with the sizing of that control. As with past versions of Windows Forms, included is the concept of height and width and the four associated limitations: MaxHeight, MaxWidth, MinHeight, and MinWidth. Additionally, as shown in this chapter, it is possible to bind controls to window borders. The layout properties aren’t the focus of this section, however. More important is the concept of layered controls. What happens when you layer an image on top of something such as a grid? Recall how the Image control you defined was bound to the four borders of its display area. In fact, the control isn’t bound to the limits of the window per se; it is bound to the limits of the grid control upon which it is explicitly layered. This layering occurs because the Image control is defined as part of the content of the grid. That content is actually a collection containing each of the layered controls for the selected control. When it comes to layout and layering, keep in mind that if a control is explicitly layered on top of another control as part of its content, then its display boundaries are by default limited by the containing control’s boundaries. This layering is as much about containing as it is layering. However, you can override this behavior using the combination of the ClipToBounds property, the LayoutClip property, and the GetLayoutClip method of the container. Note, however, that the default behavior of WPF controls is to set ClipToBounds to false and then use the LayoutClip property and the GetLayoutClip method to specify the actual clipping bounds. Resetting and manually managing the clipping behavior enables a control to be drawn outside the bounds of its parent container. That behavior is beyond the scope of this chapter, as the process is somewhat involved; the preferred behavior, when available, is to clip within the region of the parent control. The fact that your control can be drawn beyond the limits of its container is an important concept. It means your controls are no longer “contained,” but rather are truly layered. This may sound trivial, but the implications are significant. Under previous UI models, an object had a container of some sort. For example, a panel could contain other controls of certain types, but not necessarily all types. A button’s content was generally text unless you had a button configured for images, but you couldn’t really find a button configured to contain, for example, a drop-down list box, unless you wrote a custom display implementation. By moving to a more layered approach, it’s possible to create a single control that handles text, images, and other controls. Controls that support layering encapsulate a content presenter control. Thus, when you indicated that the Image control in ProVB_WPF should stretch, it stretched in accordance with the grid control. Were you to change the XAML definition of the grid control and give it a fixed height or width, then even though the window might change, the Image control would still be bound to the limits of the grid control. This behavior is explicit layering, and it is only available with certain control types. For example, WPF provides a series of different “panel” controls that are used to provide a framework for control layout. The grid is probably the one most familiar to .NET Windows Forms developers because it maps most closely to the default behavior of Windows Forms. Other similar controls include StackPanel, Canvas, DockPanel, ToolBar, and Tab-related controls. Each of these provides unique layout behavior. Because these are available as controls, which you can nest, you can combine these different layout paradigms within different Creating a WPF Application ❘ 631 Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... address that issue, it makes sense to set up the event handlers to show and hide ButtonNext; otherwise, there won’t be anything in the display Within the code you can create an event handler for Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Creating a WPF Application  ❘  64 3 the MouseLeave event and associate it with Handles StackPanelNext.MouseLeave If you previously attempted... the XAML First, delete the Label and TextBox controls and move the button that is currently on the right-hand side of the top section to the left-hand side Next, bind the window to both sides of the display and expand its size to allow it to display the full path (Of course, this is ugly, which means it will be changed as part of the upcoming UI changes.) Simpo PDF Merge and Split Unregistered Version... application (Your designer Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 63 6  ❘  Chapter 17   WPF Desktop Applications may want to skin this application later, and that frame just won’t support the look desired.) Second, the designer wants the Prev and Next buttons modified so that they are circular instead of square and use images instead of text; and just to be consistent, the designer... something reasonably meaningful Create the four necessary jpg files as 24 24 pixel images, and include an image for the resize handle for the window Next, access the MyProject page and select the Resources tab Then, select each of your jpg files and add them as Image resources to the project, as shown in Figure 17-9 Figure 17-9 Note that Visual Studio automatically places these items in the Resources folder... expect, and not using the button’s label for this task should make more sense at this point Next, you need to update the button label for when the m_curImagePath Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 6 34 ❘  Chapter 17   WPF Desktop Applications value changes This occurs only in two places: in the MainWindow_Loaded event handler and in the ButtonBrowse_Click event handler... you’ve set up around ButtonNext and replicate it around ButtonPrev You’ll need to customize the location settings and then create event handlers for the StackPanelPrev mouse events that update the visibility of the ButtonPrev control The code block that follows shows the complete XAML file to this point: Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 64 4   ❘  Chapter 17   WPF Desktop... x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/20 06/ xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/20 06/ xaml" Title="ProVB_WPF" Height="335" Width= "41 5" Name="MainWindow" WindowStyle="None" AllowsTransparency="True"> ... "http://schemas.microsoft.com/winfx/20 06/ xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/20 06/ xaml" xmlns:mc= "http://schemas.openxmlformats.org/markup-compatibility/20 06" xmlns:d= "http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> ... custom event and the custom property, which is passed with the event, the only other change is to raise that event as required Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com Creating a WPF Application  ❘  65 1 Now that we have a custom event, let’s take the updated (and much shorter) code for the main window and add a handler for this event You’ll find the new event handler at... PDF Merge and Split Unregistered Version - http://www.simpopdf.com 63 8  ❘  Chapter 17   WPF Desktop Applications At this point you can move back to the XAML designer and add the three buttons for minimize, maximize, and close For your purposes, they should reside in the upper-right corner of the display and be around the same size as your new graphics Drag a button onto the design surface and then edit . method is an event handler, and which specifi c event or events it handles. While this is a very familiar, powerful, and even recommended way of defi ning event handlers with VB and WPF, it isn. Label and TextBox controls and move the button that is currently on the right-hand side of the top section to the left-hand side. Next, bind the window to both sides of the display and expand. event handlers looks like. As a Visual Basic developer, you should fi nd this syntax very familiar. Note that the method name has been generated based on the control name and the event being handled.

Ngày đăng: 12/08/2014, 23:23

TỪ KHÓA LIÊN QUAN