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

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;

Related

Binding with parent DataContext

I'm trying to bind combobox editor in a PropertyGrid to a list.
<dxprg:PropertyGridControl SelectedObject="{Binding SelectedEmployee}">
<dxprg:PropertyDefinition Path="EmployeeCountryID">
<dxprg:PropertyDefinition.EditSettings>
<dxe:ComboBoxEditSettings
ItemsSource="{Binding Path=DataContext.Countries, ElementName=rootWindow}"
ValueMember="CountryId" DisplayMember="CountryName" />
</dxprg:PropertyDefinition.EditSettings>
</dxprg:PropertyDefinition>
</dxprg:PropertyGridControl>
This example is from a third-party control but the problem may be just general.
The "rootWindow" DataContext has been set to a ViewModel which holds a property List(of Country) that I want have as ItemsSource in a Combobox.
I was trying to access that list by setting the Combobox ItemsSource to the rootWindow.DataContext.Countries property but I don't get any data.
Tried also all those RelativeSource FindAncestor bindings but no data appeared either.
Why can't I bind through a DataContext of a given element like this?
This became solved. The problem was not with the binding at all but realated to how I defined the third-party control: Instead of EditSettings I should have defined CellTemplate -> DataTemplate.

WPF binding to a non dependency property on a control template

I'm creating a WPF custom control as an auto learning exercise. My control has a ListView inside the template. I wanto my control user be able on defining the needed columns in his own Xaml, but I did not get the strategy on how to pass the columns to the inner listview since binding with FindAncestor complain that "Columns" is not a DependencyProperty.
Wekk the questions are:
How to achieve bind a property from xaml to the template when it is not a DP
Correct my design: I think there is something wrong: if someone would change completely my template, how should I let him use the Column collection ?
why not inherit from ListView directly? Then you have all the properties you need for the ListView and can also add you own properties to the class.
Then you can apply a custom Style to your control to make it look like you want. (Here you have a basic ListView Style that you can use and expand to your needs)
Sometimes binding to a property that is not a dependency property can be solved using the Binding Mode OneWayToSource
Have you tried that?

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 with PlacementTarget and RelativeSource

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.

Passing Generic lists to a WPF usercontrol

I want to create a usercontrol that takes lists of different objects. These objects would be assigned to the control at design time. Now I want to be able to use linq to object to sort this list inside the usercontrol. Can anyone give me any ideas as how to go about it?
Add a DependencyProperty of type ObservableCollection<T> to your user control class (call it MyItemsSource for example). In your containing XAML, bind that property to your Linq collection, and inside your user control, bind your ListBox (or other ItemsControl) to the property as follows:
{Binding
RelativeSource={RelativeSource
Mode=FindAncester,
AncestorType=UserControl},
Path=MyItemsSource}
Alternatively, you can set the Name property inside the user control on the top level element (the UserControl element) to for example MyUserControl, and bind against an ElementName instead of a RelativeSource as such:
{Binding ElementName=MyUserControl, Path=MyItemsSource}

Resources