What is the most minimal xaml element that can change a DataContext? - wpf

I'm wondering what element can be used, when the only thing you want to change is the DataContext.
I'm aware that I could wrap it in a grid or something, but all of those are rather heavy weight when I just need to change the data context for a single element, so that I can more easily bind to attributes without them getting too long.

The concept of the WPF class hierarchy is described at Microsoft: WPF Architecture. There you can find the System.Windows.FrameworkElement:
The two most critical things that FrameworkElement introduces are data binding and styles.
Checking the properties of FrameworkElement, there the DataContext property is defined. This means the following capability is available:
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 XAML Resources.
The Data​Context property is now available and used at all inherited controls, which you can see at the following class hierarchy:

Related

Listview itemsource cannot see values in xaml

I have this problem with my listview itemsource, you see I'm working in WPF, and the problem comes (I think) in VB, its like blocked, this new columns I added I cannot see in xaml, the columns are there but no info, and I can see the values if I put some breakpoints in the part I specify the itemsource list, and when I do this shows up:
That lock there most be the cause of my problem, but I do not know how to take it off my collection list. HELP PLEASE.
By the way I'm using properties to create a row and later bind that to xaml
You can't see that property in the list view because it is marked as Private. According to the documentation all binding source properties must be marked as Public.
Binding Sources Overview | Microsoft Docs:
Implementing a Class for the Binding Source
(...)
Other Characteristics
The properties you use as binding source properties for a binding must be public properties of your class. Explicitly defined interface properties cannot be accessed for binding purposes, nor can protected, private, internal, or virtual properties that have no base implementation.
The little padlock that you see on the icon doesn't mean that it's locked, it's just an indication that the property is marked as Private.

Blend Behaviours - can you bind to their properties?

I am currently migrating a number of attached behaviours I have created to Blend Behaviours so that they support drag and drop within Expression Blend. I have noticed that authors of Blend behaviours tend to define the behaviour properties as dependency properties.
I have created a behaviour, TiltBehaviour, which exposes a public dependency property, TiltFactor, of type double. Within Expression Blend I can set the value of this property, however, the option to add a "Data Binding ..." is grayed out:
I have also noticed that Behaviors extend DependencyObject, therefore they do not have a DataContext and therefore cannot inherit the DataContext of the element to which they are attached. This feels like a real weakness to me!
So, the bottom-line is, if I cannot set a binding to my behaviors dependency property in Blend, and it does not inherit a DataContext, why bother using dependency properties at all? I could just use CLR properties instead.
Blend behaviors would be almost useless unless they supported binding! I recreated your tilt behavior and it supports binding in Blend 4 with no problems so I don't know exactly where you went wrong. Perhaps you can reproduce my simple example and then infer what's wrong with your setup.
Here's the (non-functional) tilt behavior with dependency property:
public class TiltBehavior : Behavior<FrameworkElement>
{
public double TiltFactor
{
get { return (double)GetValue(TiltFactorProperty); }
set { SetValue(TiltFactorProperty, value); }
}
public static readonly DependencyProperty TiltFactorProperty =
DependencyProperty.Register("TiltFactor", typeof(double), typeof(TiltBehavior), new UIPropertyMetadata(0.0));
}
Then just create a new window and drop the behavior onto the grid and Blend creates this:
<Grid>
<i:Interaction.Behaviors>
<local:TiltBehavior/>
</i:Interaction.Behaviors>
</Grid>
and the Blend "Data Binding..." option is available in the properties tab.
I tested this with both WPF and Silverlight projects. The built-in behaviors, triggers and actions all support binding by virtue of using being dependency properties and all the Blend samples use binding heavily and so this has to work.
In fact you can just drop a built-in behavior like FluidMoveBehavior onto your grid and check that Duration, which is a dependency property, supports binding. If that doesn't work, I have no idea what's going on!
Let's consider then how binding works for these strange beasts called behaviors.
As WPF or Silverlight programmers we are very familiar with binding for things like FrameworkElement. It has a property called DataContext that we can manipulate to control the default binding source and that property is inherited by nested elements when we don't override it.
But behaviors (and triggers and actions) are not of type FrameworkElement. They are ultimately derived from DependencyObject, as we might expect. But while we can using binding on any class derived from DependencyObject, our familiar DataContext is missing at this low-level and so the binding has to supply the source. That's not very convenient.
So behaviors are derived (on WPF anyway) from Animatable and Animatable is derived from Freezable. The Freezable class is where the simplicity of dependency objects intersects with the complexity of framework elements. The Freezable class is also the base class for more familiar things like brushes and image sources. These classes don't need the full complexity of a framework element, but they want to participate, in a limited way with the elements that they are associated with.
Through a complicated magical process, Freezable instances acquire an inheritance context: the framework element they are most closely associated with, and when a default binding is used (one without a source), the Freezable uses the DataContext of it's associated element instead.
In fact as you learn about behaviors the AssociatedObject is a central concept; for a behavior it is the thing that the behavior is attached to. But the important point is that all Freezable objects can use the DataContext of their AssociatedObject by proxy.
All this magic is what Josh Smith calls the:
Hillberg Freezable Trick
And so all this leads up to saying that due to the Hillberg Freezable Trick, Blend behaviors support binding using the data context of their associated element as the default source. As a result, bindings for behaviors seem to "just work" without any effort on our part. Behaviors are a thousand times more useful because of this.
Edit: dain is correct you can still bind to the DataContext which is created artificially, how often have you seen people bind to a SolidColorBrush.Color? It also works even though SolidColorBrush inherits from DependencyObject and hence has no DataContext.
See this blog post on the inheritance context.
The thing is that since the behaviours are attached, they do not appear in the logical tree and hence would not inherit a DataContext anyway.

Why setting x:Name on Window.Resources items does not work

i just curious why when i access most controls via x:Name, for resources i do so using x:Key + i cannot access it from code (could using this.Resources["keyName"])
•x:Key: Sets a unique key for each resource in a ResourceDictionary (or similar dictionary concepts in other frameworks). x:Key will probably account for 90% of the x: usages you will see in a typical WPF application's markup.
•x:Name: Specifies a run-time object name for the instance that exists in run-time code after an object element is processed. In general, you will frequently use a WPF-defined equivalent property for x:Name. Such properties map specifically to a CLR backing property and are thus more convenient for application programming, where you frequently use run time code to find the named elements from initialized XAML. The most common such property is FrameworkElement.Name. You might still use x:Name when the equivalent WPF framework-level Name property is not supported in a particular type. This occurs in certain animation scenarios.
for that reason you have to use Key for the Resources
mor on http://msdn.microsoft.com/en-us/library/ms752059.aspx
You can access resources on any FrameworkElement as long as the element contains any resources. If defined in your markup, it must have a x:Key and cannot have a x:Name.
If a Button contains the resource for example, you must access it from its Resources collection.
var resource = button.Resources["myKey"];
If you want to find a resource from an object, its parents or the application, use FindResource() instead.
var resource = this.FindResource("myKey");
I don't understand your confusion.

How can I implement a "pass-through" DataBinding?

A little background: I am loading a WPF UI from a database which is stored in a table of properties (Control type, label, margin, etc.) which I load into a class I call ControlPresenter. Basically I set ControlPresenter as the DataContext of a ContentPresenter and use a TemplateSelector to choose which type of control to load. The DataTemplate(s) load their properties off the DependencyProperties exposed by the ControlPresenter.
This all works extremely well. The problem I'm running into comes when I try to bind data (e.g. TextBox's Text property to a presenter's Name property) in other presenters (which have normal properties that implement INotifyPropertyChanged) to these controls. The control's DataContext is the associated ControlPresenter so I can't bind directly to the other presenters and I can't set up two bindings on the same dependency property (I can't bind the control and the desired presenter property to the same DP).
Possible solutions:
I could convert all of the other presenters to use DPs (extremely time consuming and prone to cause problems with inheritance)
I could use two DPs for each property I want to pass through and try to tie them together through changed notifications
Both of these seem problematic and prone to breaking so I'm hoping someone else has come up with a better solution.
Edit: I came up with a solution that works fairly well (see below). Thanks to everyone that looked at this and if you come up with a better method than I did please let me know.
There are several ways of accessing out of scope DataContexts.
1) ElementName Binding
This is probably the least useful as, in most real world scenarios, what you are trying to bind to is out of namescope anyway. But it is a way to access a parallel or parent Data Context as long as the Framework Element is within namescope.
<TextBox Text="{Binding ElementName=ControlSomewhereElseBoundToSomeOtherControlPresenter, Path=DataContext.SomeTextPropertyOnTheControlPresenter}" />
2) RelativeSource Binding
This is similar to #1 but using RelativeSource to navigate to the appropriate visual element and grab the DataContext. Of course, this assumes that the DataContext you are trying to get at is ABOVE where you currently are in the Visual Tree.
3) Use a Static Relay
You could expose your alternative ControlPresenters within a static class that acts as a facade to your ViewModel. Then, within each ViewModel construct instance properties that pass through to the static methods / properties. This is a common way for achieving shared storage across multiple View Models. I realize this technique would require you to alter your pattern a bit, but adding a simple ViewModel wrapper around these "ControlPresenter" classes seems a lot more simple than the options you described.
I ended up setting the bindings in code by setting Binding.Source to the desired ViewModel and then using the path in the database for Binding.Path. I store the bindings in a Dictionary(Of DependencyProperty, BindingBase) and when the Control loads I use BindingOperations.SetBinding to set the bindings on the control. This seems to work pretty well except for occasional order of operations issues (e.g. If you set SelectedItem/SelectedValue prior to the ItemsSource it will be set but won't display in a ComboBox).

DependencyProperty and DataBinding?

In WPF:
Can someone please explain the relationship between DependencyProperty and Databinding?
I have a property in my code behind I want to be the source of my databinding.
When does a DependencyProperty (or does it) come into play if I want to bind this object to textboxes on the XAML.
The target in a binding must always be a DependencyProperty, but any property (even plain properties) can be the source.
The problem with plain properties is that the binding will only pick up the value once and it won't change after that because change notification is missing from the plain source property.
To provide that change notification without making it a DependencyProperty, one can:
Implement INotifyPropertyChanged on the class defining the property.
Create a PropertyNameChanged event. (Backward compatibility.)
WPF will work better with the first choice.
What is the DependencyProperty?
The DependencyProperty class is one of the most important design bases hidden deep in the .Net Framework WPF.
This class is protected by sealed from the .NET Framework.
This property differs from the one-dimensional general property in that it not only stores field values, but also takes advantage of the various functions provided within the class.
Most importantly, there is a full foundation for data binding. You can also send notifications whenever you bind something.
DependencyProperty
Wpf Xaml Binding
It's already a late answer, but I'll introduce the results of my research.

Resources