What is the difference between x:Reference and ElementName?
Asked Answered
R

3

75

According to the x:Reference Markup Extension page on MSDN, x:Reference

References an instance that is declared elsewhere in XAML markup. The reference refers to an element's x:Name.

According to the Binding.ElementName Property page on MSDN, ElementName

The value of the Name property or x:Name Directive of the element of interest.

Looking back at the remarks section on the first page:

x:Reference and WPF

In WPF and XAML 2006, element references are addressed by the framework-level feature of ElementName binding. For most WPF applications and scenarios, ElementName binding should still be used. Exceptions to this general guidance might include cases where there are data context or other scoping considerations that make data binding impractical and where markup compilation is not involved.

For completeness, here is part of the remarks section on the ElementName page:

This property is useful when you want to bind to the property of another element in your application. For example, if you want to use a Slider to control the height of another control in your application, or if you want to bind the Content of your control to the SelectedValue property of your ListBox control.

Now, while I am fully aware of when and how to use the ElementName property, I don't fully understand the difference between it and the x:Reference markup extension. Can anybody please explain this and in particular, expand on the last sentence shown from the x:Reference remarks section?:

Exceptions to this general guidance might include cases where there are data context or other scoping considerations that make data binding impractical and where markup compilation is not involved.

Retrocede answered 8/10, 2013 at 9:36 Comment(0)
D
83

Basically like you said those two do almost the same. However there are small differences under the hood.

{x:Reference ...} -> returns just a reference of an object it doesn't create that "bridge" between two properties like binding would do. Behind all that a service is being used that searches for the given name in a specific scope which is usually the window itself.

{Binding ElementName="..." } -> first of all it creates that binding object then it searches for the object name but not by using the same technique under the hood as x:Reference. The search algorithm moves up and/or down in VisualTree to find the desired element. Therefore a functional VisualTree is always needed. As example when used inside a Non-UiElement, it won't work. In the end the Binding stays and does its daily bread.

This won't work:

<StackPanel>
 <Button x:name="bttn1" Visibility="Hidden">Click me</Button>
 <DataGrid>
  <DataGrid.Columns>
    <DataGridTextColumn Visibility="{Binding ElementName=bttn1, Path=DataContext.Visibility}"/>
 ....

This works:

<StackPanel>
 <Button x:name="bttn1" Visibility="Hidden">Click me</Button>
 <DataGrid>
  <DataGrid.Columns>
    <DataGridTextColumn Visibility="{Binding Source={x:Reference bttn1}, Path=DataContext.Visibility}"/>
 ....

Sort of like that :)

Drabeck answered 8/10, 2013 at 10:14 Comment(5)
So the main difference relates to whether a control is a UIElement or not?Retrocede
+1. By the way, do you have a source for this information, or is it just from experience? One thing that wasn't mentioned here, is that a child cannot x:Reference its parent (this relationship seems to depend on context, rather than on the visual tree) because this causes a circular reference issue. Sometimes the reference will also silently fail to resolve because of some other mysterious issues.Dorking
Source of this information is the source code itself :)Drabeck
Is it normal when I tried your example, the designer give me a null pointer exception even if at runtime everything works fine?Girosol
As of 2023, x:Reference should not be used in any WPF markup-compiled files.Eldreeda
W
6

ElementName is platform specific. I.e. it may or may not be present based on which platform you're using. x:Reference elevates that concept to a XAML native feature. Thus any platform that supports XAML supports x:Reference.

Wolford answered 27/12, 2016 at 21:28 Comment(1)
As of 2023, x:Reference should not be used in any WPF markup-compiled files.Eldreeda
E
2

As of 2023, looks like things have changed. Now the MS x:Reference Markup Extension page states that x:Reference cannot be used in any compiled WPF files:

x:Reference is a construct defined in XAML 2009. In WPF, you can use XAML 2009 features, but only for XAML that is not WPF markup-compiled. Markup-compiled XAML and the BAML form of XAML do not currently support the XAML 2009 language keywords and features.

So x:Reference should be avoided in any XAML file set to "Page" for the Build Action property in VS (or set to "Compile" and possibly others).

For example, MainWindow.xaml has its Build Action set to "Page" by default in any new WPF project.

Eldreeda answered 9/3, 2023 at 13:8 Comment(2)
I also noticed this statement, indicating that I should not use x:Reference in an XAML file whose build action is "Page". However, I tried using x:Reference in a Page, and it just worked fine. I'm using VS2022, .NET 7. I can't figure out why or how.Nabal
@Nabal That's interesting. I just started using VS 2022 myself, and created a new WPF app project using .NET 7. Despite it being .NET 7, the XAML namespace headers show that WPF still needs to use XAML 2006 (which according to MS) should not allow use of x:Reference in markup-compiled WPF files. Perhaps there was an update/upgrade to WPF in the latest versions of .NET that now allow for this, and they just forgot to update this MS page with the new info?Eldreeda

© 2022 - 2024 — McMap. All rights reserved.