WPF binding with PlacementTarget and RelativeSource - wpf

Can you explain the following WPF code:
DataContext="{Binding Path=PlacementTarget,RelativeSource={x:Static RelativeSource.Self}}">
I find it extremely confusing. What is placement target and what is relative source?

This looks like a hack that is used for popup-elements such as ContextMenus and Popup-windows.
The problem with these elements is, that they are disconnected from the visual tree of your window. Therefore the DataContext is not available. The PlacementTarget is a link to an element of the visual-tree.
Mostly you will find a binding path like PlacementTarget.Tag where in the source element the Tag property has been set to the DataContext but in some situations, the element itself is also meaningful, such as in your example.
Assuming that the above code is used in a ToolTip or a ContextMenu, the DataContext will be set to the control that "owns" the element.
Look at the post from (Gishu +1) for an explanation of the mechanics.

Every FrameworkElement has a DataContext that is an arbitrary object. The default source for a data binding is that DataContext. You can use RelativeSource.Self to change the source for a binding to the FrameworkElement itself instead of its DataContext. So the RelativeSource part just moves you "up one level" from the DataContext of the FrameworkElement to the FrameworkElement itself. Once you are at the FrameworkElement you can specify a path to any of its properties. If the FrameworkElement is a Popup, it will have a PlacementTarget property that is the other FrameworkElement that the Popup is positioned relative to.
In short, if you have a Popup placed relative to a TextBox for example, that expression sets the DataContext of the Popup to the TextBox and as a result {Binding Text} somewhere in the body of the Popup would bind to the text of the TextBox.

This is binding the DataContext of a thing (UI Control? need to see more of the code snippet ) to its own PlacementTarget property value.
RelativeSource is used to indicate the source object relative to the binding target. The path property indicates the name of the property on the source object.

Related

XAML property path for templates

I have the following hierarchy in my XAML:
Grid
Ruler
Ruler
ScrollViewer
ItemsControl
ItemsControl.ItemsPanel
ItemsPanelTemplate
DrawingCanvas
Here Ruler and DrawingCanvas are my UserControls. DrawingCanvas exposes a property named MousePosition that I want both Rulers to bind to. After reading about PropertyPath Syntax, I tried the following:
Chip="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Mode=OneWay, Path=Children[2].(ScrollViewer.Content).(ItemsControl.ItemsPanel).(local:DesignerCanvas.MousePosition).X}"
but this doesn't seem to work. What am I doing wrong?
Generally in these circumstances you would simply name the element you wish to bind to. It is much less brittle than finding your way through the tree:
Chip="{Binding MousePosition.X, ElementName=myCanvas}"
However, because your canvas is part of the ItemsControl template, the ElementName will not be visible to elements outside the ItemsControl.
In order to bind the two together, you need some intermediate property that both can see. One way would be to declare a DependencyProperty in your code-behind for the view. Both your Canvas and Rulers could then bind to that property using ElementName on the view root.
Another alternative is to hijack the Tag property that every element has, so in your case you could use ItemsControl.Tag as the intermediary:
Chip="{Binding Tag.X, ElementName=myItemsControl}"
<DrawingCanvas MousePosition={Binding Tag,
ElementName=myItemsControl,
mode=OneWayToSource} />
You are selecting element 3 in the Children collection which will map to the fourth element inside of the Grid. You are looking for Children[2].

How to get rid of using ElementName in WPF bindings in XAML

I am building a WPF application and I have some DependencyProperties in my window's codebehind (actually a big bunch of them). I want to bind a textbox to one of these string values. If I use {Binding ObjectName} it just doesn't work and it complains about not finding the property in the output. If I use {Binding ObjectName, ElementName=window} (where window is my Window's instance name), it works. But I have lots of bindings and I don't want to use the ElementName property each time. Is there any shortcut that will default all the element names to the window objects, as all of my bindings have the same element?
Thanks,
Can.
The default source of a binding is FrameworkElement.DataContext so you have to set the DataContext property of your window to the instance of your window e.g. DataContext = this;

Setting DataContext makes PropertyChanged null in UserControl

I have a WPF application which uses a WPF user control.
The user control exposes a DependencyProperty to which I would like to bind to in my WPF application.
As long as my user control does not set its own DataContext this works and I am able to listen to changes in the DependencyProperty.
However the moment I set the DataContext the PropertyChanged being called is null.
What am I missing here?
Code sample:
https://skydrive.live.com/redir.aspx?cid=367c25322257cfda&page=play&resid=367C25322257CFDA!184
DependencyProperty has inheritance property, so if you don't set the UserControlDP's DataContext, the DataContext is inherited from the MainWindow's DataContext. In this case, the UserControlDP's DataContext in your code below is set as MainWindow_ViewModel. Thus, the binding is correctly executed.
<usercontrol:UserControlDP Width="200" Height="100"
TestValue="{Binding TestValueApp, Mode=TwoWay, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}"
Margin="152,54,151,157"></usercontrol:UserControlDP>
In the other case, UserControlDP's DataContext is set as UserControlDP_ViewModel, so the binding is broken. You can see the first exception message as the following at the debug window.
System.Windows.Data Error: 40 : BindingExpression path error: 'TestValueApp' property not found on 'object' ''UserControlDP_ViewModel' (HashCode=24672987)'. BindingExpression:Path=TestValueApp; DataItem='UserControlDP_ViewModel' (HashCode=24672987); target element is 'UserControlDP' (Name=''); target property is 'TestValue' (type 'Object')
Consider setting the DataContext on one of the elements contained within UserControl rather than on UserControl itself.
Thanks for the input and clarifying the details.
After giving it some thought I took the easy way out and removed the ViewModel from the control.
MVVM for the application but no MVVM for the user control.
This way I do not use any bindings in the user control, instead use Dependency Properties which are bound to in the Main application.

WPF Custom Control - Binding a template item to a Path

In a WPF Custom Control template, is there any way that I can do the following in XAML?:
var selItemText = this.GetTemplateChild("PART_SelectedItemText") as TextBlock;
var binding = new Binding("SelectedItem." + DisplayMemberPath);
binding.RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent);
selItemText .SetBinding(TextBlock.TextProperty, binding);
Note that the interesting part of this statement is the binding constructor - I am building up a path based on both some text I specify ("SelectedItem."), and the path provided by the user.
The consumer would use the control similar to:
<c:MyControl DisplayMemberPath="Description" />
short answer: no, it's not possible to get this entirely in xaml within the controltemplate
your possibilities are:
use what you have (possibly using attached properties / a behavior to make it more MVVM-like)
use a MultiBinding one binding to the "SelectedItem" the other to "DisplayMemberPath" and your MultiValueConverter using Reflection to reflect down the DisplayMemberPath (may be a bit ugly)
create a class that inherits from Binding and exposes Properties that you can bind the DisplayMemberPath to and changes the underlying Binding (read here for how you can do this) (complicated)
use Reflection to instantiate a MS.Internal.Data.DisplayMemberTemplateSelector / build something similar
think about if your design is right. Other than your Control being some kind of ItemsControl (if that was the case you should inherit from ItemsControl and use the DisplayMemberPath you get there), I don't see why you shouldn't use a Binding on the outside like <c:MyControl DisplayMember="{Binding SelectedItem.Description}" /> and in your ControlTemplate use a TemplateBinding to bind to "DisplayMember"
You can split it to two different bindings. Have SelectedItem binds to a toplevel control of TextBlock and TextBox.Text bind to DisplayMemberPath as TemplateBinding.

WPF Binding Syntax Question

I've seen this syntax show up, and have tried to google for it's definition to no avail; what does it mean when a dp is bound this way?
<Grid>
<ContentControl Content="{Binding}"/>
</Grid>
I was under the assumption that you have to bind to some property on the DataContext, or another element, but this appears to bind to nothing.
I believe it means you are binding to the root of whatever the binding context is. So if you use this syntax in a datatemplate that is part of some sort of list control, you would be binding to the root level of whatever the parent control (the list control) was binding to.
I believe {Binding} refers to the DataContext itself.
edit (clarification): By DataContext I mean the current level DataContext. For example, if your window's DataContext is bound to a List, then setting ItemsSource on a ListBox control in your window to {Binding} would bind the ListBox to the List itself, not a property of the List, like Count.
{Binding} is for {Binding [CurrentDataContext]}
{Binding} means that you want to Bind to the the current DataContext which could be set on the object itself. If no DataContext is set on the current object, then it will walk up the VisualTree and find the closest Parent that has a DataContext.

Resources