Binding ElementName. Does it use Visual Tree or Logical Tree - wpf

Having {Binding ElementName=foo}, will it lookup visual or logical tree?
Of logical and visual trees in WPF | Data See, Data Do
When does the logical tree matter?
When looking up a name, such as in
{Binding ElementName=Foo}, the search
walks up the ancestry looking for a
name scope, again just as it does for
inheritable properties.
ElementName binding in Silverlight via Attached Behaviours
In order to enable this, WPF provides
ElementName and RelativeSource
bindings, giving you a powerful
mechanism for locating other elements
within your visual tree to bind to
EDIT:
It looks like the Logical Tree used for binding by ElementName.
Argument # 1.
According to MSDN article FrameworkElement Class:
FrameworkElement extends UIElement
and adds the following capabilities:
Support for data binding and
dynamic resource references: The
property-level support for data
binding and resources is implemented
by the DependencyProperty class and
embodied in the property system, but
the ability to resolve a member value
that is stored as an Expression (the
programming construct that underlies
both data binding and dynamic
resources) is implemented by
FrameworkElement. For more
information, see Data Binding Overview
and Resources Overview.
Argument # 2.
ElementName points to x:Name, so this name should be found some how. There is a NameScope concept.
For most scenarios, the FindName
methods exposed on FrameworkElement
and FrameworkContentElement are more
appropriate methods to call to search
for elements by name. The Name
properties exposed by FrameworkElement
and FrameworkContentElement are more
appropriate properties to use to set
the initial name as markup attributes.
And the RegisterName methods exposed
on FrameworkElement and
FrameworkContentElement is necessary
to establish a name into a specific
namescope (there is no NameScope
member that can do this directly; you
must set the current namescope first
to use RegisterName).
On the other hand, Visual class neither have FindName method, nor implement INameScope.

I think it's logical tree. When using ControlTemplates, you're replacing one visual tree with another, but I don't think you can reference the names defined inside of the ControlTemplate.
For example:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.Resources>
<ControlTemplate x:Key="Foo" TargetType="Button">
<Border x:Name="border" Background="Red">
<Label Content="{TemplateBinding Content}"></Label>
</Border>
</ControlTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button x:Name="buttonFoo" Background="Green" HorizontalAlignment="Center" VerticalAlignment="Center" Template="{DynamicResource Foo}">Foo</Button>
<Label x:Name="labelBar" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Background="{Binding ElementName=border, Path=Background}">Bar</Label>
</Grid>
</Page>
Doesn't find the element named "border" in the ControlTemplate, but changing ElementName in labelBar's binding to "buttonFoo" makes the Background Green, as expected.

The ElementName property of a binding in a sense (see below answer) works off of the logical tree because one is using ElementName to divine a specific control solely on the logical tree in the Xaml.
will it lookup visual or logical tree?
The premise you propose is wrong, there is no lookup per-se on either tree. One is simply setting a Source property for reflection operation used by the binding instead of defaulting to the inherited DataContext of the logical tree.
If one reads the documentation of Binding.ElementName Property (System.Windows.Data) (bolding mine):
"...the ElementName property is one of the ways you can explicitly set the source of a Binding and override the inherited data context."
The source is any instantiated object which is within the current operations namespace which can be accessed and reflected off of.
No more no less and most likely will be in the Logical Tree (but doesn't have too) because people name there logical items in Xaml, but also could be in the visual tree.
See Data Binding Overview for more info.

Related

WPF- Binding properties in a DataTemplate

I'm building a window with a set of rows that share the same layout, but their contents should be different, eg:
| (Label Content:)"Name1" | (Textbox Text)"SomeText" |
| (Label Content:)"Name5" | (Textbox Text)"OtherText" |
I've defined a DataTemplate which basically holds a Grid specifying the size of each column, holds all the elements it requires (a few labels, textboxes, etc.) and sets their common properties.
<UserControl.Resources>
<DataTemplate x:Key="AxisRangeEntry" x:Shared="False">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="50" />
....
</Grid.ColumnDefinitions>
<Label x:Name="MyLabel" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center">
...
<TextBox x:Name="MyTextbox" Grid.Column="2" Width="110" HorizontalContentAlignment="Right" />
...
</Grid>
</DataTemplate>
</UserControl.Resources>
Then in my window I start adding the data template as ContentControls in a stack panel:
<ContentControl ContentTemplate="{StaticResource AxisRangeEntry}" />
<ContentControl ContentTemplate="{StaticResource AxisRangeEntry}" />
....
I'm struggling to figure out how I can define certain properties of controls inside the DataTemplate to be bindable to, and bind them to a static value/external property when I start defining the ContentControls. Effectively each ContentControl would need to be able to define things like it's MyLabel content and MyTextbox text.
I've previously created CustomControls, which had DependencyProperties on them, which I could then bind to when adding them on another window. With a DataTemplate however I'm not sure how I would define these fields as bindable and bind to them when including a new version of the template.
Any help would be appreciated.
From what it sounds like, you are not using the MVVM pattern.
For your situation, I'd recommend using MVVM -- take a look at this article for a quick intro for something that would fit your case (ItemsControl with an ItemTemplate)
What you would do is create an ObservableObject to represent each row, and then bind the collection of ObservableObjects to an ItemsControl's ItemsSource, with the ItemTemplate set to the DataTemplate you created. In the DataTemplate, you would specify each binding to the property on the ObservableObject's row, and WPF would bind to the correct instance for each row.
http://www.wpf-tutorial.com/list-controls/itemscontrol/
Either way, DataTemplates are primarily used for templating a certain data-type. If you really need to implement the view in this way, a custom UserControl with dependency properties would be the way to go.
You present a dynamic nature of items to be bound, so this answer will attempt to provide guidance within the parameter's set.
...[to] define certain properties of
controls inside the DataTemplate to be bindable to,
Within a template the binding will default to the parents data context. Simply saying {Binding} will default to that item in the data context. If the bound item has a specific property then use {Binding MyPropertyName}. Just verify that the parent, or its ancestors have a valid data context.
Think of data templates in its final location, as if you had hard coded it there. It will behave the same....
and bind them to a static value/external property when I start defining the
ContentControls.
Since this sounds like it is in a custom control, the datacontext will be the ultimate consumer's datacontext and most likely the datacontext will be worthless.
If it is on a custom control, then use named binding and bind it to a property on the control. For example the control's name, in XAML, is given the name "MyControl" (x:Name="MyControl")and in the template binding, one can path directly to it such as
{Binding MyCustomControlDependencyProperty, ElementName=MyControl}
created CustomControls, which had Dependency properties
With the above rules one can still, and should IMHO, use dependency properties of the custom control to pass on the information from the consumer to the the datatemplate which will use it dynamically..

Is DependcenyProperty always inherited?

Is there a mechanism that is blocking the inheritance of DependecyProperty or some values are set locally by some elements?
I have two examples that I don't understand:
<Button Background="AntiqueWhite" Height="40" Width="50" FontSize="10">
<Button>Test</Button>
</Button>
<TextBlock Text="Test" Background="AntiqueWhite" Height="40" Width="50" FontSize="10">
<TextBlock />
</TextBlock>
In Button element the child button is not inheriting background / height / width but it is inheriting fontsize even though all of the properties are DependencyProperty.
In TextBlock element situation is the same but we have another DependencyProperty (Text).
I understand how priorities work. Local value has greater priority over Inherited one. But where can i get information if a control sets something by itself? Or maybe there is some other mechanism that is preventing some DependencyProperties from being inherited?
See this article: http://msdn.microsoft.com/en-us/library/vstudio/ms751554%28v=vs.100%29.aspx
DependencyProperties have PropertyMetadata (relevant class is FrameworkPropertyMetadata)
One of the flags described is the Inherits flag (http://msdn.microsoft.com/en-us/library/vstudio/system.windows.frameworkpropertymetadata.inherits%28v=vs.100%29.aspx)
Excerpt:
Inherits. By default, dependency properties do not inherit values.
OverridesInheritanceBehavior allows the pathway of inheritance to also
travel into a visual tree, which is necessary for some control
compositing scenarios. NoteNote
The term "inherits" in the context of property values means something
specific for dependency properties; it means that child elements can
inherit the actual dependency property value from parent elements
because of a WPF framework-level capability of the WPF property
system. It has nothing to do directly with managed code type and
members inheritance through derived types. For details, see Property
Value Inheritance.

What is the difference between x:Reference and ElementName?

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.
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 :)
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.

How do you navigate a complex Visual Tree in order to re-bind an existing element?

In the above image, child is a ContentPresenter. Its Content is a ViewModel. However, its ContentTemplate is null.
In my XAML, I have a TabControl with the following structure:
<local:SuperTabControlEx DataContext="{Binding WorkSpaceListViewModel}"
x:Name="superTabControl1" CloseButtonVisibility="Visible" TabStyle="OneNote2007" ClipToBounds="False" ContentInnerBorderBrush="Red" FontSize="24" >
<local:SuperTabControlEx.ItemsSource>
<Binding Path="WorkSpaceViewModels" />
</local:SuperTabControlEx.ItemsSource>
<TabControl.Template>
<ControlTemplate
TargetType="TabControl">
<DockPanel>
<TabPanel
DockPanel.Dock="Top"
IsItemsHost="True" />
<Grid
DockPanel.Dock="Bottom"
x:Name="PART_ItemsHolder" />
</DockPanel>
<!-- no content presenter -->
</ControlTemplate>
</TabControl.Template>
<TabControl.Resources>
<DataTemplate DataType="{x:Type vm:WorkSpaceViewModel}">
....
WorkSpaceViewModels is an ObservableCollection of WorkSpaceViewModel. This code uses the code and technique from Keeping the WPF Tab Control from destroying its children.
The correct DataTemplate - shown above in the TabControl.Resource - appears to be rendering my ViewModel for two Tabs.
However, my basic question is, how is my view getting hooked up to my WorkSpaceViewModel, yet, the ContentTemplate on the ContentPresenter is null? My requirement is to access a visual component from the ViewModel because a setting for the view is becoming unbound from its property in the ViewModel upon certain user actions, and I need to rebind it.
The DataTemplate is "implicitly" defined. The ContentPresenter will first use it's ContentTemplate/Selector, if any is defined. If not, then it will search for a DataTemplate resource without an explicit x:Key and whose DataType matches the type of it's Content.
This is discussed here and here.
The View Model shouldn't really know about it's associated View. It sounds like there is something wrong with your Bindings, as in general you should not have to "rebind" them. Either way, an attached behavior would be a good way to accomplish that.
I think the full answer to this question entails DrWPF's full series ItemsControl: A to Z. However, I believe the gist lies in where the visual elements get stored when a DataTemplate is "inflated" to display the data item it has been linked to by the framework.
In the section Introduction to Control Templates of "ItemsControl: 'L' is for Lookless", DrWPF explains that "We’ve already learned that a DataTemplate is used to declare the visual representation of a data item that appears within an application’s logical tree. In ‘P’ is for Panel, we learned that an ItemsPanelTemplate is used to declare the items host used within an ItemsControl."
For my issue, I still have not successfully navigated the visual tree in order to get a reference to my splitter item. This is my best attempt so far:
// w1 is a Window
SuperTabControlEx stc = w1.FindName("superTabControl1") as SuperTabControlEx;
//SuperTabItem sti = (SuperTabItem)(stc.ItemContainerGenerator.ContainerFromItem(stc.Items.CurrentItem));
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(stc);
//ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(sti);
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
The above code is an attempt to implement the techniques shown on the msdn web site. However, when I apply it to my code, everything looks good, except myDataTemplate comes back null. As you can see, I attempted the same technique on SuperTabControlEx and SuperTabItem, derived from TabControl and TabItem, respectively. As described in my original post, and evident in the XAML snippet, the SuperTabControlEx also implements code from Keeping the WPF Tab Control from destroying its children.
At this point, perhaps more than anything else, I think this is an exercise in navigating the Visual Tree. I am going to modify the title of the question to reflect my new conceptions of the issue.

What is the meaning of x:Name in xaml (WPF) and its use with Storyboard

<Border Name="ItemBorder" Margin="5 5 0 5" BorderBrush="Black" BorderThickness="1" Height="75" Width="75">
<Border.Background>
<SolidColorBrush x:Name="ItemBorderBrush" Color="LightBlue"/>
</Border.Background>
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="someEvent">
<BeginStoryboard>
<Storyboard TargetName="ItemBorderBrush" TargetProperty="Color" Duration="0:0:1" >
<!--Storyboard TargetName="ItemBorder" TargetProperty="Background.Color" Duration="0:0:1"> -->
<ColorAnimation To="White"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
I'll try to explain my question clearly. The Storyboard Target name, when it is "ItemBorder" (the commented out line) works intermittently. Sometimes I get an error that the name "ItemBorder" cannot be found in the scope.
I decided to follow a style from an MSDN example of this, and change the color property directly on the brush, instead of having the target of the storyboard be the border, and changing the color of the border's brush by property (the commented out line). This seems to work.
However, Name="ItemBorderBrush" does not compile because Name is not a property of SolidColorBrush so I use x:Name="ItemBorderBrush" Both Name and x:Name are accepted for the Border. Why is this?
What does the x: mean (how is x:Name different from Name), and why would having the Name property of border only work with the storyboard sometimes?
The x: prefix is simply setting an attribute from a seperate namespace:
Within the namespace declarations in
the root tag of many XAML files, you
will see that there are typically two
XML namespace declarations. The first
declaration maps the overall WPF
client / framework XAML namespace as
the default:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
The second declaration maps a separate
XAML namespace, mapping it (typically)
to the x: prefix.
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
The relationship between these
declarations is that the x: prefix
mapping supports the intrinsics that
are part of the XAML language
definition, and WPF is one
implementation that uses XAML as a
language and defines a vocabulary of
its objects for XAML. Because the WPF
vocabulary's usages will be far more
common than the XAML intrinsics
usages, the WPF vocabulary is mapped
as the default
So, the reason that Name and x:Name both work on Border is because Border has a property called Name. It also supports the XAML Intrinsic usage of x:Name (which is what WPF uses to create the named instance of the class).
However, SolidColorBrush doesn't have the property called Name so it only supports the XAML Intrinsic usage of x:Name.
There really is only one name in XAML, the x:Name. A framework, such as WPF, can optionally map one of its properties to XAML's x:Name by using the RuntimeNamePropertyAttribute on the class that designates one of the classes properties as mapping to the x:Name attribute of XAML.
The reason this was done was to allow for frameworks that already have a concept of "Name" at runtime, such as WPF. In WPF, for example, FrameworkElement introduces a Name property.
In general, a class does not need to store the name for x:Name to be useable. All x:Name means to XAML is generate a field to store the value in the code behind class. What the runtime does with that mapping is framework dependent.
So, why are there two ways to do the same thing? The simple answer because there are two concepts mapped onto one property. WPF wants the name of an element preserved at runtime (which is usable through Bind, among other things) and XAML needs to know what elements you want to be accessible by fields in the code behind class. WPF ties these two together by marking the Name property as an alias of x:Name.
In the future, XAML will have more uses for x:Name, such as allowing you to set properties by referring to other objects by name, but in 3.5 and prior, it is only used to create fields.
Whether you should use one or the other is really a style question, not a technical one. I will leave that to others for a recommendation.
See also AutomationProperties.Name VS x:Name, AutomationProperties.Name is used by accessibility tools and some testing tools.
refer In WPF, what are the differences between the x:Name and Name attributes?

Resources