Trong WPF, sự khác biệt giữa các thuộc tính x: Tên và Tên là gì?


574

Tiêu đề nói lên tất cả. Đôi khi dường như các thuộc tính Namex:Namecó thể hoán đổi cho nhau.

Vì vậy, sự khác biệt cuối cùng giữa chúng là gì, và khi nào nên sử dụng cái này hơn cái kia?

Có bất kỳ hiệu suất hoặc bộ nhớ liên quan đến việc sử dụng chúng sai cách?


Phản hồi đề nghị rằng sử dụng x:Nametất cả thời gian hoạt động tốt. Tôi đã phải thay đổi nó thành Namenếu không tôi không thể tham chiếu điều khiển trong mã .xaml.cs của mình vì vậy tôi sẽ giả định rằng nó không còn là trường hợp hoạt động tốt mọi lúc.
Ortund

1
Về rollback của bạn, ý nghĩa bổ sung nào được truyền đạt bởi cụm từ "tiêu đề nói lên tất cả", Drew? Có phải nó không dư thừa? (Lý do chỉnh sửa của tôi là tôi có xu hướng không khuyến khích các cụm từ điền vào cuộc trò chuyện - đây không phải là thông tin nhiều hơn "Tôi tự hỏi nếu bạn có thể giúp tôi").
tạm dừng

Câu trả lời:


481

Thực sự chỉ có một tên trong XAML x:Name. Một khung công tác, chẳng hạn như WPF, có thể tùy ý ánh xạ một trong các thuộc tính của nó sang XAML x:Namebằng cách sử dụng lớp RuntimeNamePropertyAttributetrên chỉ định một trong các thuộc tính của lớp làm ánh xạ tới thuộc tính x: Name của XAML.

Lý do điều này được thực hiện là để cho phép các khung đã có khái niệm "Tên" khi chạy, chẳng hạn như WPF. Trong WPF, ví dụ, FrameworkElementgiới thiệu một thuộc tính Tên.

Nói chung, một lớp không cần lưu trữ tên x:Nameđể có thể sử dụng được. Tất cả các x:Namephương tiện để XAML là tạo một trường để lưu trữ giá trị trong mã phía sau lớp. Những gì thời gian chạy làm với ánh xạ đó là phụ thuộc khung.

Vậy, tại sao có hai cách để làm điều tương tự? Câu trả lời đơn giản là vì có hai khái niệm được ánh xạ lên một thuộc tính. WPF muốn tên của một phần tử được bảo toàn trong thời gian chạy (có thể sử dụng thông qua Bind, trong số những thứ khác) và XAML cần biết những phần tử nào bạn muốn có thể truy cập được bằng các trường trong mã phía sau lớp. WPF liên kết hai cái này với nhau bằng cách đánh dấu thuộc tính Name là bí danh của x: Name.

Trong tương lai, XAML sẽ có nhiều cách sử dụng hơn cho x: Name, chẳng hạn như cho phép bạn đặt thuộc tính bằng cách tham chiếu đến các đối tượng khác theo tên, nhưng trong 3.5 và trước đó, nó chỉ được sử dụng để tạo các trường.

Cho dù bạn nên sử dụng cái này hay cái kia thực sự là một câu hỏi về phong cách, không phải là một câu hỏi kỹ thuật. Tôi sẽ để lại cho người khác cho một đề nghị.

Xem thêm Tự động hóa. Tên VS x: Tên , Tự động hóa. Tên được sử dụng bởi các công cụ trợ năng và một số công cụ kiểm tra.


2
Trong Visual Studio 2010, thuộc tính Name được đặt (không phải x: Name) khi bạn chỉnh sửa XAML thông qua trình thiết kế. Có vẻ như MS khuyến khích việc sử dụng Tên trên x: Tên vì vậy tôi đoán đó là tiêu chuẩn defacto.
Tinh vân

11
Tôi không nghĩ rằng cả hai có thể hoán đổi cho nhau. Việc đặt tên điều khiển người dùng yêu cầu x:Namebởi vì Namesẽ không tạo ra một trường được nhận dạng theo mã phía sau. Tôi vẫn không biết tại sao điều này xảy ra, mặc dù.
Libor

5
Họ không có nghĩa là tôi cũng không ngụ ý họ đã làm. Trong WPF, nếu một phần tử có thuộc Nametính thì chúng có nghĩa tương tự. Nếu phần tử không có thuộc Nametính, bạn phải sử dụng x:Name.
chuckj

90

Chúng không giống nhau.

x:Namelà một khái niệm xaml, được sử dụng chủ yếu để tham chiếu các yếu tố. Khi bạn cung cấp cho một phần tử thuộc tính x: Name xaml, "chỉ định x:Nametrở thành tên của một trường được tạo trong mã cơ bản khi xaml được xử lý và trường đó giữ tham chiếu đến đối tượng." ( MSDN ) Vì vậy, đây là trường do nhà thiết kế tạo, có quyền truy cập nội bộ theo mặc định.

Namelà thuộc tính chuỗi hiện có của a FrameworkElement, được liệt kê như bất kỳ thuộc tính phần tử wpf nào khác ở dạng thuộc tính xaml.

Kết quả là, điều này cũng có nghĩa là x:Namecó thể được sử dụng trên một phạm vi rộng hơn của các đối tượng. Đây là một kỹ thuật để cho phép mọi thứ trong xaml được tham chiếu bởi một tên cụ thể.


6
Vậy tại sao Tên hoặc x: Tên có thể được sử dụng với Binding.EuityName? Có vẻ như thuộc tính x: Name không chỉ được sử dụng để đặt tên cho một trường trong mã được tạo, mà nó còn có sẵn trong siêu dữ liệu khi chạy.
Drew Noakes

Nó là một trường được tạo như Tên trường trong thuộc tính Thiết kế của trình soạn thảo WinForms. Ở đó bạn đặt một tên trong danh sách tài sản và nó trở thành tên của một trường. Đây là hành vi tương tự. Tất nhiên nó có sẵn trong thời gian chạy vì nó là một trường nội bộ được biên dịch thành mã phía sau. Binding.EuityName kiểm tra một trong hai trường hợp, đó là trình biên tập xaml "ma thuật", bản thân x: Name không phải là phép thuật.
Kenan EK

39

x: Tên và Tên đang tham chiếu các không gian tên khác nhau.

x: name là một tham chiếu đến không gian tên x được xác định theo mặc định ở đầu tệp Xaml.

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Chỉ cần nói Tên sử dụng mặc định bên dưới không gian tên.

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

x: Tên đang nói sử dụng không gian tên có bí danh x . x là mặc định và hầu hết mọi người rời bỏ nó nhưng bạn có thể thay đổi nó thành bất cứ điều gì bạn thích

xmlns:foo="http://schemas.microsoft.com/winfx/2006/xaml"

vì vậy tài liệu tham khảo của bạn sẽ là foo: name

Xác định và sử dụng không gian tên trong WPF


OK hãy nhìn vào điều này một cách khác. Giả sử bạn kéo và thả nút vào trang Xaml của mình. Bạn có thể tham khảo 2 cách x: têntên này . Tất cả xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns: x = "http://schemas.microsoft.com/winfx/2006/xaml" là các tham chiếu đến nhiều không gian tên . Vì xaml giữ không gian tên Điều khiển (không phải 100% trên đó) và bản trình bày giữ FrameworkEuitylớp Nút có mẫu kế thừa là:

Button : ButtonBase
ButtonBase : ContentControl, ICommandSource
ContentControl : Control, IAddChild
Control : FrameworkElement
FrameworkElement : UIElement, IFrameworkInputElement, 
                    IInputElement, ISupportInitialize, IHaveResources

Vì vậy, như mọi người mong đợi bất cứ điều gì kế thừa từ FrameworkEuity sẽ có quyền truy cập vào tất cả các thuộc tính công khai của nó. Vì vậy, trong trường hợp của Nút, nó nhận được thuộc tính Tên từ FrameworkEuity, ở đầu cây phân cấp. Vì vậy, bạn có thể nói x: Name hoặc Name và cả hai sẽ truy cập getter / setter từ FrameworkEuity.

Tài liệu tham khảo MSDN

WPF định nghĩa một thuộc tính CLR được sử dụng bởi các bộ xử lý XAML để ánh xạ nhiều không gian tên CLR vào một không gian tên XML duy nhất. Các XmlnsDefinitionAttribute thuộc tính được đặt ở mức lắp ráp trong mã nguồn sản xuất lắp ráp. Mã nguồn lắp ráp WPF sử dụng thuộc tính này để ánh xạ các không gian tên phổ biến khác nhau, chẳng hạn như System.Windows và System.Windows.Controls, vào không gian tên http://schemas.microsoft.com/winfx/2006/xaml/presentation .

Vì vậy, các thuộc tính lắp ráp sẽ trông giống như:

PresentationFramework.dll - XmlnsDefDefAttribution:

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Data")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Navigation")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Shapes")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Documents")]

[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "System.Windows.Controls")]  

1
Tôi không nghĩ rằng đó là sự thật mà http://schemas.microsoft.com/winfx/2006/xamlgiữ Controlkể từ khi bạn có thể sử dụng trực tiếp trong XAML mà không có một 'x' namespace:<Control />
Drew Noakes

23

Cả hai đều giống nhau, rất nhiều thành phần khung hiển thị một thuộc tính tên, nhưng đối với những người không có thể sử dụng x: name - tôi thường chỉ gắn với x: name vì nó hoạt động cho mọi thứ.

Kiểm soát có thể hiển thị tên mình là Tài sản phụ thuộc nếu họ muốn (vì họ cần sử dụng Tài sản phụ thuộc đó trong nội bộ) hoặc họ có thể chọn không sử dụng.

Thêm chi tiết trong msDN tại đâyđây :

Một số ứng dụng mức khung WPF có thể tránh được việc sử dụng thuộc tính x: Name, vì thuộc tính phụ thuộc Tên như được chỉ định trong không gian tên WPF cho một số lớp cơ sở quan trọng như FrameworkEuity / FrameworkContentEuity đáp ứng cùng mục đích này. Vẫn còn một số tình huống XAML và khung phổ biến trong đó mã truy cập vào một phần tử không có thuộc tính Tên là cần thiết, đáng chú ý nhất là trong các lớp hỗ trợ hoạt hình và bảng phân cảnh nhất định. Chẳng hạn, bạn nên chỉ định x: Tên trên các mốc thời gian và các biến đổi được tạo trong XAML, nếu bạn có ý định tham chiếu chúng từ mã.

Nếu Tên có sẵn dưới dạng một thuộc tính trên lớp, Tên và x: Tên có thể được sử dụng thay thế cho nhau như các thuộc tính, nhưng sẽ xảy ra lỗi nếu cả hai được chỉ định trên cùng một phần tử.


4
Nếu không có sự khác biệt, thì tại sao lại có hai cách làm giống nhau? Cả hai cách đều tồn tại trong phiên bản đầu tiên của WPF.
Drew Noakes

@Steve, tôi không đánh giá thấp bất kỳ câu trả lời nào cho câu hỏi này, mặc dù cho đến nay vẫn chưa có câu trả lời nào phù hợp.
Drew Noakes

Tôi không thấy câu trả lời không chỉ cung cấp cho bạn câu trả lời mà còn cung cấp cho bạn các liên kết đến MSDN để biết thêm thông tin về chủ đề không phù hợp? :-)
Steven Robbins

5
@Steve câu trả lời ban đầu của bạn không giải quyết câu hỏi của tôi, do đó bình luận của tôi. Tôi không tìm kiếm niềm tin mù quáng "làm theo cách này", mà là một câu trả lời sâu sắc giải thích tại sao hai cách tồn tại, ngay cả khi một trong số chúng luôn hoạt động. Kỹ thuật chính xác! = Thích hợp. Cập nhật của bạn tốt hơn nhiều.
Drew Noakes

1
Rất nhiều câu trả lời tương tự ở đây: wpfwiki.com/WPF%20Q16.4.ashx x: Tên đang đặt tên điều khiển để sử dụng trong mã phía sau. Một số lớp sẽ cung cấp một thuộc tính Tên cho cùng một mục đích. Đối với các lớp này, không có sự khác biệt giữa x: name và name.
Vegar

11

X: Tên có thể gây ra vấn đề bộ nhớ nếu bạn có các điều khiển tùy chỉnh. Nó sẽ giữ một vị trí bộ nhớ cho mục nhập NameScope.

Tôi nói không bao giờ sử dụng x: Tên trừ khi bạn phải.


Đã đồng ý. Hoạt động trên một ứng dụng kiosk có nhiều rò rỉ bộ nhớ và độ phân giải của nhóm nhà phát triển trước đó chỉ là để khởi động lại. Phần lớn các rò rỉ đã được xác định dễ dàng. Tuy nhiên, sau khi sửa những lỗi được tìm thấy qua IntelliTrace và JustTrace, một số ref vẫn lảng tránh bộ sưu tập rác ngầm và rõ ràng. Tôi đọc: support.scichart.com/index.php?/News/NewsItem/View/21/NH Tìm thấy rằng giảm x: Đặt tên hiệu suất được cải thiện hơn nữa.
MachinusX

2
Theo hiểu biết của tôi, điều này ảnh hưởng đến cả Tênx: Tên vì cả hai đều được thêm vào NameScope. Nếu bạn cần một Tên trên thành phần của bạn, sẽ không có xung quanh nó. Bạn có thể repro trong mã trên một phần tử không có tên thông qua FrameworkElement.RegisterName("elementname"). Tuy nhiên, nếu bạn gọi FrameworkElement.UnregisterName("elementname")nó có thể là "hủy đăng ký".
Adam Caviness

8

Sự khác biệt duy nhất là nếu bạn đang sử dụng Điều khiển người dùng vào một điều khiển từ Cùng một hội thì Tên sẽ không xác định điều khiển của bạn và bạn sẽ gặp lỗi "Sử dụng x: Tên cho các điều khiển trong cùng một Hội đồng". Vì vậy, x: Name là phiên bản WPF của các điều khiển đặt tên trong WPF. Tên chỉ được sử dụng như một di sản Winform. Họ muốn phân biệt cách đặt tên các điều khiển trong WPF và winforms khi họ sử dụng các thuộc tính trong Xaml để xác định các điều khiển từ các hội đồng khác mà họ đã sử dụng x: cho Tên của điều khiển.

Chỉ cần lưu ý không đặt tên cho điều khiển chỉ vì mục đích giữ nó vì nó nằm trong bộ nhớ dưới dạng trống và nó sẽ đưa ra cảnh báo rằng Tên đã được áp dụng cho điều khiển nhưng nó không bao giờ được sử dụng.


8

Tên :

  1. chỉ có thể được sử dụng cho hậu duệ của FrameworkEuity và FrameworkContentEuity;
  2. có thể được đặt từ mã phía sau thông qua SetValue () và giống như thuộc tính.

x: Tên :

  1. có thể được sử dụng cho hầu hết các yếu tố XAML;
  2. KHÔNG thể được đặt từ mã phía sau thông qua SetValue (); nó chỉ có thể được đặt bằng cú pháp thuộc tính trên các đối tượng vì nó là một lệnh.

Sử dụng cả hai lệnh trong XAML cho một FrameworkEuity hoặc FrameworkContentEuity sẽ gây ra một ngoại lệ: nếu XAML được đánh dấu biên dịch, ngoại lệ sẽ xảy ra trên trình biên dịch đánh dấu, nếu không nó sẽ xảy ra khi tải.


7

x:Name có nghĩa là: tạo một trường trong mã phía sau để giữ một tham chiếu đến đối tượng này.

Name có nghĩa là: đặt thuộc tính tên của đối tượng này.


Điều này không hoàn toàn đúng; cả hai đều có thể truy cập được từ codebehind, nhưng thật thú vị chỉ có x: Tên có thể được cập nhật khi chạy. Hạt dẻ.

4

Tôi luôn sử dụng biến thể x: Name. Tôi không biết nếu điều này ảnh hưởng đến bất kỳ hiệu suất, tôi chỉ thấy nó dễ dàng hơn cho lý do sau đây. Nếu bạn có các điều khiển người dùng của riêng bạn cư trú trong một hội đồng khác, thì thuộc tính "Tên" sẽ không luôn luôn đủ. Điều này giúp dễ dàng hơn khi chỉ gắn thuộc tính x: Name.


4
Nếu không có sự khác biệt, thì tại sao lại có hai cách làm giống nhau? Cả hai cách đều tồn tại trong phiên bản đầu tiên của WPF.
Drew Noakes

3

Đây không phải là một mục WPF mà là một XML tiêu chuẩn và BtBh đã trả lời đúng, x đề cập đến không gian tên mặc định. Trong XML khi bạn không đặt tiền tố một phần tử / thuộc tính với một không gian tên, nó giả sử bạn muốn không gian tên mặc định. Vì vậy, gõ chỉ Namelà không có gì nhiều hơn một bàn tay ngắn cho x:Name. Thông tin chi tiết về các không gian tên XML có thể được tìm thấy tại văn bản liên kết


Bị cám dỗ đến -1 x: đề cập đến một không gian tên XML khác, đúng, nhưng đó không thực sự là một câu trả lời hữu ích cho Q, đó là khi nào bạn cần sử dụng cái này không cái nào khác. : /
Tim Lovell-Smith

2

Một trong những câu trả lời là x: name sẽ được sử dụng bên trong các ngôn ngữ chương trình khác nhau như c # và name sẽ được sử dụng cho khung. Thành thật mà nói đó là những gì nó nghe với tôi.


2

Tên x: Tên được chỉ định trở thành tên của một trường được tạo trong mã bên dưới khi XAML được xử lý và trường đó giữ tham chiếu đến đối tượng. Trong Silverlight, sử dụng API được quản lý, quá trình tạo trường này được thực hiện bởi các bước mục tiêu MSBuild, cũng chịu trách nhiệm tham gia các lớp một phần cho tệp XAML và mã phía sau. Hành vi này không nhất thiết phải là ngôn ngữ XAML được chỉ định; đó là cách triển khai cụ thể mà Silverlight áp dụng để sử dụng x: Name trong các mô hình lập trình và ứng dụng của nó.

Đọc thêm về MSDN ...


2

Khi bạn khai báo một phần tử Nút trong XAML, bạn đang đề cập đến một lớp được xác định trong thời gian chạy windows được gọi là Nút.

Nút có nhiều thuộc tính như nền, văn bản, lề, ..... và một thuộc tính được gọi là Tên.

Bây giờ khi bạn khai báo một Nút trong XAML giống như tạo một đối tượng ẩn danh tình cờ có một thuộc tính được gọi là Tên.

Nói chung, bạn không thể tham chiếu đến một đối tượng ẩn danh, nhưng trong bộ xử lý XAML của khung WPF cho phép bạn tham chiếu đến đối tượng đó bằng bất kỳ giá trị nào bạn đã cung cấp cho thuộc tính Tên.

Càng xa càng tốt.

Một cách khác để tạo một đối tượng là tạo một đối tượng được đặt tên thay vì đối tượng ẩn danh. Trong trường hợp này, không gian tên XAML có một thuộc tính cho một đối tượng được gọi là Tên (và vì nó nằm trong không gian tên XAML nên có X :) mà bạn có thể đặt để bạn có thể xác định đối tượng của mình và tham chiếu đến nó.

Phần kết luận:

Tên là một thuộc tính của một đối tượng cụ thể, nhưng X: Tên là một thuộc tính của đối tượng đó (có một lớp xác định một đối tượng chung).


0

Nghiên cứu của tôi là x:Namenhư thế giới biến. Tuy nhiên, Namenhư địa phương khác nhau. Điều đó có nghĩa là x: Tên bạn có thể gọi nó ở bất cứ đâu trong tệp XAML của bạn nhưng Tên thì không.
Thí dụ:

<StackPanel>
<TextBlock Text="{Binding Path=Content, ElementName=btn}" />
<Button Content="Example" Name="btn" />
</StackPanel>
<TextBlock Text="{Binding Path=Content, ElementName=btn}" />

Bạn không thể Bindingsở hữu Contentcủa Buttonchữ với cái tên là "btn" bởi vì nó bên ngoàiStackPanel

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.