I think one of the core changes of WPF is that the control model has undergone an important change. In the big aspect, the controls (most of them) in the window do not have independent hwnd. In addition, the control can provide a variety of forms through the so-called template.
In this article, let's talk about contentcontrol. The first part is to dynamically add controls and search controls.
What is contentcontrol? In fact, most of the controls of WPF, including windows, are inherited from contentcontrol.
Sometimes, we need to dynamically add some widgets after the window is out. For example, in the simplest scenario: we need to do a mine clearance task.ProgramThe mine clearance program determines the number of mines to be displayed based on the user's difficulty.
For ease of understanding, you can see the following three pictures
Okay. Let's take a look at how it works in Windows Forms?
Using System; Using System. Windows. forms; Namespace Windowsformsapplication1 { Public Partial Class Form1: FORM {Public Form1 () {initializecomponent ();} Private Void Button#click ( Object Sender, eventargs e ){ // For the basic version, instantiate 6*6 with a total of 64 buttons Createbutton (6, 6 );} Private Void Button2_click ( Object Sender, eventargs e ){ // Advanced edition, instantiate 9*9, 81 buttons in total Createbutton (9, 9 );} Private Void Createbutton ( Int X,Int Y) {panel1.suspendlayout (); panel1.controls. Clear (); // The margins in all four directions are 5 Int Width = (panel1.width-(x + 1) * 5)/X; Int Height = (panel1.height-(Y + 1) * 5)/y; For ( Int I = 0; I <X; I ++ ){ For ( Int J = 0; j <Y; j ++) {button bt = New Button () {width = width, height = height, Left = I * width + 5, Top = J * height + 5}; panel1.controls. add (BT) ;}} panel1.resumelayout ();}}}
We can take a little time to explain it. In fact, we use a loop to dynamically create a batch of buttons and add them to the panel's controls set.
So is it feasible to put the same idea in WPF? Let's take a look.
First, there are several major containers for layout control in WPF.
- Canvas is positioned based on absolute positions, much like the Panel mechanism above;
- Stackpanel is based on the stream mode. It does not have the concept of absolute positioning. a batch of controls are either arranged from left to right or from top to bottom.
- Grid, which is probably the most commonly used, provides better control organization by row and column. In fact, canvas and stackpanel can also be embedded in the grid. They can combine to construct a complex enough interface.
So, let's try to use canvas to achieve a similar effect as Windows Forms.
So, ourCodeWhat is the difference?
The first part is the XAML code.
< Window X: Class = "Wpfapplication1.window1" Xmlns = "Http://schemas.microsoft.com/winfx/2006/xaml/presentation" Xmlns: x = "Http://schemas.microsoft.com/winfx/2006/xaml" Title = "My Mine Clearance Program" Height = "516" Width = "592" > < Grid > < Button Height = "23" Horizontalalignment = "Left" Margin = "20, 12, 0, 0" Name = "Button1" Verticalalignment = "TOP" Width = "75" Click = "Button#click" > Elementary </ Button > < Button Height = "23" Horizontalalignment = "Left" Margin =" Name = "Button2" Verticalalignment = "TOP" Width = "75" Click = "Button2_click" > Advanced </ Button > < Canvas Margin = "20, 41, 12" Name = "Canvas1" /> </ Grid > </ Window >
The second part is C # code
Using System. windows; Using System. Windows. controls; Namespace Wpfapplication1 {/// <Summary> /// Interaction logic of window1.xaml /// </Summary> Public Partial Class Window1: window { Public Window1 () {initializecomponent ();} Private Void Button#click ( Object Sender, routedeventargs e) {createbutton (6, 6 );} Private Void Button2_click ( Object Sender, routedeventargs e) {createbutton (9, 9 );} Private Void Createbutton ( Int X, Int Y) {canvas1.children. Clear (); // The margins in all four directions are 5 Double Width = ( This . Canvas1.actualwidth-(x + 1) * 5)/X; Double Height = ( This . Canvas1.actualheight-(Y + 1) * 5)/y; For ( Int I = 0; I <X; I ++ ){For ( Int J = 0; j <Y; j ++) {button bt = New Button () {width = width, height = height}; canvas. settop (BT, J * height + 5); canvas. setleft (BT, I * width + 5 ); // These two statements are critical. The positioning of a button in a canvas is not a concept of its own left and top. Canvas1.children. Add (BT );}}}}}
We found the following differences:
1. There is no controls concept, but a children attribute that represents all sub-content.
2. There are some special methods for locating sub-elements for different containers. For example, the settop method of canvas.