日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Name与x:Name的关系--转载

發(fā)布時(shí)間:2025/4/5 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Name与x:Name的关系--转载 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

小序:

如果想用Google搜包含冒號(hào)的內(nèi)容怎么辦?比如我想搜x:Name這個(gè)字符串……

原來(lái),應(yīng)該是這樣——x::Name

這世道,連搜索也要加轉(zhuǎn)義,全民程序員,要不要人活了?

正文:

從第一天學(xué)習(xí)XAML語(yǔ)言開始,我就一直沒分清為什么對(duì)于一個(gè)XAML標(biāo)簽既可以設(shè)置它的Name又可以設(shè)置它的x:Name。問(wèn)過(guò)一些同事,大家好像對(duì)這種比較孔乙己的問(wèn)題不太感興趣。今天花了些時(shí)間看了看,收獲還挺多的。與大家分享一下。

首先,讓我們剖析一下XAML代碼與C#代碼之間的關(guān)系。

大家都知道,XAML是“用來(lái)設(shè)計(jì)UI”的,設(shè)計(jì)師用XAML設(shè)計(jì)出來(lái)的UI其后臺(tái)代碼(程序邏輯)可以由程序員用C#或者VB去寫——這叫做Code-behind。實(shí)際上,設(shè)計(jì)師用XAML和程序用C#都是在構(gòu)建同一個(gè)類,換句話說(shuō)就是:把一個(gè)類劈成兩半,與UI相關(guān)的那半由設(shè)計(jì)師用XAML寫,與邏輯相關(guān)的那半由程序員用C#寫。

.NET之所以支持這種劈開寫的功能,得益于partial這個(gè)關(guān)鍵字。請(qǐng)大家看這兩段代碼

  • ????//?For?UI
  • ????public?partial?class?Car
  • ????{
  • ????????Color?bodyColor;
  • ????????Color?windowColor;
  • ????????Polygon?door;
  • ????????Polygon?seat;
  • ????}
  • ????//?For?logic
  • ????public?partial?class?Car
  • ????{
  • ????????public?void?Accelerate()?{?/*80,?90...?120,?140....1200...flying...*/}
  • ????????public?void?Break()?{/*zizizizizizizizizi....*/?}
  • ????}
  • ????public??class?Car
  • ????{
  • ????????//?UI
  • ????????Color?bodyColor;
  • ????????Color?windowColor;
  • ????????Polygon?door;
  • ????????Polygon?seat;
  • ????????//?logic
  • ????????public?void?Accelerate()?{?/*80,?90...?120,?140....1200...flying...*/}
  • ????????public?void?Break()?{/*zizizizizizizizizi....*/?}
  • ????}
  • 實(shí)際效果是完全一樣的。只是前者是把UI和邏輯劈開寫,后者是混在一起寫罷了。

    劈開的確是劈開了,但讓設(shè)計(jì)師用C#代碼去實(shí)現(xiàn)UI恐怕不現(xiàn)實(shí)——讓Blend直接生成C#不是不可能是事情,只是C#描述UI太不直觀了。于是,微軟更進(jìn)一步,把界面描述語(yǔ)言又向設(shè)計(jì)師方向推進(jìn)了一層,也就是XAML語(yǔ)言。于是,開發(fā)和設(shè)計(jì)的格局就變成了這樣:

    有了XAML和將XAML解析為C#/VB的解析器,設(shè)計(jì)師們就能以自己最高的工作效率與程序員們合作開發(fā)軟件了。目前關(guān)于XAML是如何解析成C#/VB的資料非常少。

    Name揭秘

    下面讓我們把目光集中在XAML->C#的解析上來(lái),看看Name和x:Name的本質(zhì)是什么。

    讓我們看一段代碼:

  • <Window?x:Class="WpfApplication2.Window1"
  • ????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  • ????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  • ????Title="Window1"?Height="100"?Width="300"?Background="SteelBlue">
  • ????<StackPanel>
  • ????????<TextBox?Name="textBox1"/>
  • ????????<TextBox?Name="textBox2"/>
  • ????????<Button?Content="Show?Name"?Click="Button_Click"/>
  • ????</StackPanel>
  • ????<x:Code>
  • ????????<![CDATA[
  • ???????
  • ????????private?void?Button_Click(object?sender,?RoutedEventArgs?e)
  • ????????{
  • ????????????Button?btn?=?e.OriginalSource?as?Button;
  • ????????????textBox1.Text?=?btn.Name;
  • ????????????textBox2.Name?=?"Made_in_China";
  • ????????????textBox2.Text?=?textBox2.Name;
  • ????????}
  • ?????
  • ????????]]>
  • ????</x:Code>
  • </Window>
  • 運(yùn)行結(jié)果是:

    我用XAML定義了三個(gè)UI元素,其中兩個(gè)TextBox是有Name的。凡是你在XAML代碼里設(shè)置了它的Name,那么在C#代碼里就會(huì)有一個(gè)對(duì)應(yīng)的變量。這可也很好解釋,看看IL程序集就知道了——

    不難看出,XAML解析器會(huì)為XAML代碼中設(shè)置了Name的元素聲明同名的引用變量,而且設(shè)置Name的元素則不會(huì)有引用變量生成(不過(guò)這個(gè)元素對(duì)應(yīng)的對(duì)象是存在的,并且是VisualTree/LogicalTree上的結(jié)點(diǎn))。

    通過(guò)上面的代碼,我看可以看出,Name的作用有兩個(gè):

    1. 告訴XAML解析器為設(shè)置了Name的元素聲明對(duì)應(yīng)的引用變量(本例中是textBox1和textBox2),變量名使用Name的值。

    2. 將XAML元素對(duì)應(yīng)的對(duì)象(本例中是兩個(gè)TextBox的實(shí)例)的Name屬性設(shè)置為Name的值。

    注意,引用變量一旦聲明之后名字就不能改了,但對(duì)象的Name屬性仍然可以改(示例中我就把由textBox2變量引用著的實(shí)例的Name屬性改成Made_in_China了。)

    讓我們?cè)偻谏铧c(diǎn)兒——TextBox的Name屬性是從哪兒繼承來(lái)的呢?查一查MSDN,原來(lái)是從FrameworkElement那兒繼承來(lái)的。這個(gè)Name屬性是非常重要的——如果你想在一棵“樹”上查找叫某個(gè)名字的元素,調(diào)用“樹根”的FindName方法就可以做到了。特別需要注意的是——FindName所使用的參數(shù)是對(duì)象Name屬性的值而不是引用著這個(gè)對(duì)象的變量的名字。如果你的程序里只在XAML里設(shè)置了一次Name,那么引用變量的名字和對(duì)象Name屬性的值恰好一樣。但如果你改變了對(duì)象Name屬性的值,那可就要小心了!請(qǐng)看下面的代碼:

  • <Window?x:Class="WpfApplication2.Window1"
  • ????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  • ????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  • ????Title="Window1"?Height="100"?Width="300"?Background="SteelBlue">
  • ????<StackPanel>
  • ????????<TextBox?Name="textBox1"/>
  • ????????<TextBox?Name="textBox2"/>
  • ????????<Button?Content="Show?Name"?Click="Button_Click"/>
  • ????</StackPanel>
  • ????<x:Code>
  • ????????<![CDATA[
  • ???????
  • ????????private?void?Button_Click(object?sender,?RoutedEventArgs?e)
  • ????????{
  • ????????????textBox2.Name?=?"Made_in_China";
  • ????????????//this.RegisterName("Made_in_China",?this.textBox2);
  • ????????????TextBox?t?=?this.FindName("Made_in_China")?as?TextBox;
  • ????????????if(t==null)
  • ????????????{
  • ??????????????return;
  • ????????????}
  • ????????????else
  • ????????????{
  • ??????????????MessageBox.Show("OK");
  • ????????????}
  • ????????}
  • ?????
  • ????????]]>
  • ????</x:Code>
  • </Window>
  • 注意,除非我取消對(duì)第17行的注釋,不然,盡管我已經(jīng)把textBox2.Name改成了Made_in_China,但由于這個(gè)新名字還沒有被注冊(cè)(即沒有使用RegisterName方法將Made_in_China和textBox2所引用的對(duì)象關(guān)聯(lián)起來(lái)),我們?nèi)匀徊荒芡ㄟ^(guò)FindName找到它。

    我知道這段話挺拗口,不過(guò)有一點(diǎn)你想通過(guò)某種方法查找由DataTemplate自動(dòng)生成的UI元素時(shí),或許應(yīng)該跑來(lái)讀一讀這段繞口令:P

    最后再啰嗦一句:為什么這個(gè)Name屬性可以起到在運(yùn)行時(shí)被當(dāng)作查找標(biāo)識(shí)呢?是因?yàn)镕rameworkElement被一個(gè)名為RuntimeNamePropertyAttribute的attribute所修飾。這個(gè)attribute明確指定,FrameworkElement的Name屬性具備了作為查找標(biāo)識(shí)的資格。TextBox等類派生自FrameworkElement,自然也有這個(gè)功能。下面是FrameworkElement類的聲明。

    ?

    [RuntimeNamePropertyAttribute("Name")] [StyleTypedPropertyAttribute(Property?=?"FocusVisualStyle",?StyleTargetType?=?typeof(Control))] [XmlLangPropertyAttribute("Language")] public?class?FrameworkElement?:?UIElement,? ????IFrameworkInputElement,?IInputElement,?ISupportInitialize { ????//... }

    x:Name揭秘

    ?

    ?

    x:Name的x加一個(gè)冒號(hào),說(shuō)明它來(lái)自x這個(gè)名稱空間。這個(gè)名稱空間是定義在XAML的根元素上的。也就是這句:

  • xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
  • 這個(gè)x就是XAML的字頭了。這個(gè)名稱空間的本意就是告訴我們——這個(gè)名稱空間里所裝的元素都與XAML解析有關(guān)。比如,我在代碼里還使用了x:Code,把本來(lái)應(yīng)該呆在C#代碼里的內(nèi)容請(qǐng)到XAML里來(lái)了。

    可見,x:Name與Name根本不是一個(gè)層面上的東西——Name是直接與元素和面向?qū)ο缶幊滔嚓P(guān)的東西;x:Name是XAML語(yǔ)言解析層面上的東西。

    如果我們把上面代碼中的所有Name都改成x:Name,所有效果都是一樣的。

    不知道XAML中標(biāo)有x:的內(nèi)容是不是會(huì)被“預(yù)處理”一下。

    Name與x:Name關(guān)系揭秘

    不過(guò),如果你的邏輯感比較強(qiáng),你會(huì)發(fā)現(xiàn)這樣一個(gè)問(wèn)題——為一個(gè)XAML元素聲明對(duì)應(yīng)的引用變量,這不是面向?qū)ο缶幊虒用娴臇|西而是XAML解析層的東西。而且,如果Name在語(yǔ)義學(xué)上“恪守本分”的話,它應(yīng)該只去設(shè)置一下對(duì)象的Name屬性值而不去管是不是聲明變量的事兒。

    大膽設(shè)想一下,你會(huì)猜到,當(dāng)XAML解析器發(fā)現(xiàn)一個(gè)元素的Name被設(shè)置了,就會(huì)去調(diào)用x:Name的那套機(jī)制。也就是說(shuō),引用變量是在x:Name機(jī)制被調(diào)用的時(shí)候聲明的。同樣,如果你設(shè)置的是元素的x:Name,XAML解析器會(huì)在聲明變量之后再去給實(shí)例的Name屬性設(shè)置值。

    這樣的猜想能夠得到證實(shí)嗎?讓我們?cè)贛SDN里搜刮一下。

    在x:Name的注釋里,我們能找到這段話:

    Under the standard build configuration for a WPF application project that uses XAML, partial classes, and code-behind, the specified x:Name becomes the name of a field that is created in the underlying code when XAML is processed, and that field holds a reference to the object.

    而在FrameworkElement.Name屬性的文檔里,又能找到這句話:

    This property essentially provides a WPF framework-level convenience property to set the XAML x:Name Attribute.

    也就是說(shuō),Name的確會(huì)去調(diào)x:Name那套機(jī)制。為什么這么做?可能是為了寫起來(lái)方便。不過(guò),我真不太喜歡這種攪和在一起的風(fēng)格。我寧可使用Name去給對(duì)象的Name屬性賦值而使用x:Name去聲明變量。

    貌似“Under the standard build configuration ”這句話有點(diǎn)玄機(jī)。不知道非standard編譯配置會(huì)有什么樣的效果,怎樣才能自定義編譯配置呢?

    不喜歡這種風(fēng)格的原因還在于:Name和x:Name互相調(diào)用會(huì)在某些邏輯下出問(wèn)題,特別是“先有雞還是先有蛋”這種情況下。

    關(guān)于在XAML中使用同一個(gè)程序集中的User Control

    說(shuō)到“先有雞還是先有蛋”的問(wèn)題,讓我想起了另一個(gè)困擾自己很久的問(wèn)題。請(qǐng)看下面的代碼:

    假設(shè)我有這樣一個(gè)project,

    現(xiàn)在我想把MyControl用在我的Window1里。如果代碼寫成這樣:

  • <Window?x:Class="WpfApplication.Window1"
  • ????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  • ????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  • ????xmlns:local="clr-namespace:WpfApplication"
  • ????Title="Window1"?Height="300"?Width="300">
  • ????<Grid>
  • ????????<local:MyControl?Name="myControl"/>
  • ????</Grid>
  • </Window>
  • 當(dāng)編譯的時(shí)候,會(huì)報(bào)出錯(cuò)誤:

    最讓人哭笑不得的原因就是“因?yàn)镸yControl是在同一個(gè)程序集里,你就得使用x:Name而不是Name!”這算什么解釋?跟是不是同一個(gè)程序集有什么關(guān)系?

    =====================================

    崔維福的補(bǔ)充:

    "跟是不是同一個(gè)程序集有什么關(guān)系" 具體來(lái)說(shuō)還是有關(guān)系的。你一定知道Name不能和x:Name同時(shí)用,因?yàn)樵赽uild的時(shí)候他知道這兩個(gè)做了相同的工作,什么工作呢,就是做在“類名.g.cs”,中添加了后臺(tái)代碼,x:Name是Attribute,而Name是DP,編譯器可以挖掘Attribute來(lái)為自己的后臺(tái)添加內(nèi)容,但是不能用Name來(lái)添加,因?yàn)樽约哼€沒有被構(gòu)造完全呢。所以呢就是告訴你,要用x:Name,要不就把這個(gè)contro放到別的project下,它好能把它構(gòu)造出來(lái)!希望我解釋的夠清楚!

    作者:

    感謝崔先生的批注,您對(duì)技術(shù)精益求精的精神讓我非常景仰,向您學(xué)習(xí)、致敬!

    轉(zhuǎn)載于:https://www.cnblogs.com/tianyutingxy/archive/2011/02/23/1962078.html

    總結(jié)

    以上是生活随笔為你收集整理的Name与x:Name的关系--转载的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。