ThisArticleIt comes from such a problem. What are the differences between the following two methods? (Note: The header is a custom DP .)
<Tabitem Header= "{Binding header, elementname = Window }">
<Textbox Text= "{Binding header, elementname = Window }"
Name= "Headername"/>
</Tabitem>
And
<Datatemplate X: Key= "Tabtemplate">
<Textbox Text= "{Binding header, elementname = Window }"
Name= "Headernameintemplate"/>
</Datatemplate>
<Tabitem Header= "{Binding header, elementname = Window }"
Contenttemplate= "{Staticresource tabtemplate }"/>
One is to put a textbox directly in the tabitem, and the other is to put it indirectly through the datatemplate. There is no difference between the two methods in appearance. There is no difference in the structure of the control when you get the visual tree in xamlpad.
Figure 1. directly use textbox
Figure 2. textbox In Template
In the development of WPFProgramDatatemplate is often used to generate the UI from data in mvvm mode. Of course, we also want to use the same behavior as we do not need a datatemplate. At present, the two interfaces look the same, and the same is true for visualtree. The behavior should be the same.
But the desire is beautiful, but the realization is cruel. Although the two different implementation methods look the same, the behavior is different. Here is an example program to see if you can find the differences between the two implementation methods?
Figure 3. example running diagram
If you have not guessed the reason, or are too lazy to study the exampleCode, Let's continue with the analysis below.
The above analysis has always been based on the comparison of spatial similarity. The two implementation methods are indeed the same from the perspective of spatial structure. Let's take a look at the process.
First, let's take a look at the tabcontrol and examples.
1. When textbox is directly placed in tabitem, the content of tabitem is a real control.
2. When datatemplate is used, the content of tabitem in the above sample code is empty.
3. Although tabcontrol has multiple tabitems, only one tabitem is displayed. More importantly, no matter how tabitem is switched, tabcontrol always uses the same contentpresenter to display the content in the current tabitem. Refer to the Blue section in Figure 1 and 2. The control is the main part of tabcontrol. It will not change when you switch the tab.
When you switch between different tabitems in tabcontrol, if you find that content is a control, such as textbox In the example, the textbox is displayed. If the content is an object, the datatemplate is used at the same time. The datatemplate will be applied.
The problem is,How is datatemplate applied?
Microsoft's official documents on datatemplate only show you how to use datatemplate, but it does not seem to introduce how datatemplate works (maybe, but it has never been found ).
This document explains datatemplate.
"The WPF data templating model provides you with great flexibility to define the presentation of your data ."
That is to say, it provides great flexibility to display (or generate) the data interface.
However, Microsoft has not read the full text. What is the difference between ememplate and datatemplate. Basically, this article introduces the advantages of datatemplate. A disadvantage is not described. However, when comparing different technologies, we usually compare their advantages and disadvantages. If you have never understood the disadvantages of a technology before, you can use it rashly, And you will inevitably encounter unexpected situations that will affect the development progress.
The following analysis of the datatemplate principle is based on the actual results of the datatemplate. If you do not have any official materials, there may be many errors. please let us know.
The purpose and effect of datatemplate are as follows. Datatemplate is a runtime behavior. The ememplate does not work before the program loads data. At this time, other non-datatemplate controls have been loaded. After the data is loaded, WPF will further load the control in the datatemplate based on the data type or the data type specified by the control itself.
Consider the following situations:
1. The two controls use the same datatemplate. Take the example in the previous article as an example. Both tabitems use the same ememplate and there is a textbox in the datatemplate. In the last generated interface, in the two tabitems, is it two different textbox or one textbox?
2. Take the above example and change it slightly so that two tabitems use different ememplate. When switching between two tabitems, does the datatemplate generated control of the tabitem that you cannot see exist or has been recycled?
You can try again first.
For the previous example. The answer to question 1 is the same textbox. You don't have to answer the 2nd questions.
However, for WPF as a whole, the answer is uncertain. The answer to the question depends on whether the datatemplate has set the X: Shared attribute (this attribute is strange and cannot be automatically generated by the intelliisence of VS) and the controls on which the datatemplate is used. In the preceding example, this attribute is not set. The default value is true. Because tabcontrol only has one contentpresenter, the items in the ememplate are shared. Well, it's complicated.
If the X: Shared attribute is set to false, the answer to the 1st questions is different textbox. The answer to the 2nd questions is that they will be recycled. However, if textbox is directly placed in tabitem, the textbox in each tabitem will not be recycled during tabitem switching.
Are there any problems with these features of datatemplate? Yes, and it is not small for commercial software with high requirements. Currently, the following two methods are found.
1. The cursor position is lost.
2. databinding does not updatesource.
First, let's explain the first question. The cursor position is lost. This problem is not big, not small. We open Visual Studio and open several moreSource codeFile, and then switch between the files to see if the cursor position will be saved? However, after datatemplate is used, no matter how X: shared is set (the result is different), the cursor position is incorrect. We have to maintain the cursor position again.
Question 2: Classify and discuss it. If X: shared is true, it is the default value. The two tabitems use the same textbox. When you switch the tab, The lostfocus event of the textbox will not be triggered, and the databinding will not update the datasource. If X: shared is false, the textbox in the previous tab will be recycled and lost when the tab is switched. If databinding can be updatesource, it will become. Will the lostfocus be triggered first before the textbox is recycled. After the experiment, the lostfocus event is not triggered before the textbox is recycled. (I would like to thank my colleague shelvin yuan for discovering this problem. .)
There are more solutions for problem 2. You can set the updatesourcetrigger attribute of databinding. You can customize a textbox. When recycling, manually trigger lostfocus and set X: Shared to false, you can also manually updatesource when switching the tab.
But none of these solutions seem perfect. Isn't datatemplate able to avoid these side effects? Unfortunately, I have not found the best solution, so that the effect of using ememplate is the same as that of not using datatemplate.
Currently, datatemplate is completely a runtime behavior. I can think of a solution that allows the programmer to set the behaviors of datatemplate, which can be both runtime behaviors and static behaviors similar to pre-compiled commands. For example, you can add an X: isstatic attribute to the datatemplate to set its behavior. Take the above Code as an example. If the compiler finds that this attribute is true, it will expand the items in the datatemplate and inline them into the tabitem, just like directly using textbox.
But this is just a good wish. Currently, you can only find workaround.