Binding doesn't work on DependencyObject created in XAML - c#

I'm trying to pass multiple CommandParameters in XAML with the use of a custom class.
I have created a class called ValueCommandArgs that inherits from DependencyObject and has two DepencyProperties (lets call them Value1 and Value2 for this example).
The button which is supposed to call a command and pass this object looks like this:
<Button Command="{Binding ChangeValueCommand}" Content="Execute Command">
<Button.CommandParameter>
<args:ValueCommandArgs Value1="{Binding TestValue1}" Value2="{Binding TestValue2}" />
</Button.CommandParameter>
</Button>
I do get an ValueCommandArgs-Object in my command as paramter, however the properties Value1 and Value2 are always null/empty.
I know this can be solved with a MultiBinding and Converter, but I think the way I'm trying it would be a cleaner approach.
Why doesn't this work?

A Binding needs a source object to be able to provide a value. When the Binding source is not specified (with Source or ElementName etc.) eg: Value1="{Binding TestValue1}" the DataContext of the element is used.
The args:ValueCommandArgs object does not inherit the DataContext from the Button element because property value inheritance is particularly about how property values can inherit from one element to another on the basis of the parent-child relationships within a tree of elements.
The button object does not include the value of the CommandParameter property in its logical nor the visual tree.
In many cases the need for such a CommandParameter with multiple bound values can be avoided by binding the values directly to the ViewModel.
When it can't be avoided you can use a different type of binding markup extension like: https://github.com/JohanLarsson/Gu.Reactive#ninjabinding that will use the root FrameworkElement as the source of the binding.
Another approach would be a binding proxy technique shown in this blog post: How to bind to data when the DataContext is not inherited

Related

What is different between {binding} and inherit in wpf datacontext?

I have some problems about datacontext binding.
My app has virtualization listbox.
Sometimes Button is not fired dataContextChanged.
So I found this.
<Grid DataContext={Binding ~~>
<Button DataContext={Binding}/>
</Grid>
<Grid DataContext={Binding ~~>
<Button/>
</Grid>
My Code is first one. but It's not fired DataContextChanged sometimes, So I changed code to second one.
snoop said first one is from inherit, and second one is from parentTemplate.
What is different first one and second one?
TL;DR:
SomeProperty={Binding} will bind the SomeProperty to the ENTIRE DataContext object from the parent. SomeProperty does not have to be the DataContext from the child. In this special case I don't think there is any difference, since the DataContext is inherited anyways. You are simply explicitly stating, what is already the default. Discussed here
More Info:
Here is an explanation from the official documentation for
<Button DataContext={Binding}/>
As long as the binding already has a data context (for example, the
inherited data context coming from a parent element), and whatever
item or collection being returned by that context is appropriate for
binding without requiring further path modification, a binding
declaration can have no clauses at all: {Binding}. This is often the
way a binding is specified for data styling, where the binding acts
upon a collection. For more information, see Using Entire Objects as a Binding Source.
and from here
<ListBox ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="true"/>
The above example uses the empty binding syntax: {Binding}. In this
case, the ListBox inherits the DataContext from a parent DockPanel
element (not shown in this example). When the path is not specified,
the default is to bind to the entire object. In other words, in this
example, the path has been left out because we are binding the
ItemsSource property to the entire object. (See the Binding to
collections section for an in-depth discussion.)
In general, the DataContext is inherited from parent elements. So in your 2nd example the button gets the DataContext from the Grid. Example
"ItemsControl" are special: Example
I don't know what ~~ is, is this meant to be a placeholder?
Some more information on Bindings and Markup Extensions:
Link1
Link2
Link3

xaml - How to specify which ContentTemplateSelector to use?

I've seen a ton of examples where a content control's ContentTemplateSelector property is assigned a StaticResource.
Example: <ContentControl Content="{Binding}" ContentTemplateSelector="{StaticResource MyTemplateSelector}"/>
MSDN states:
Typically, you create a DataTemplateSelector when you have more than
one DataTemplate for the same type of objects and you want to supply
your own logic to choose a DataTemplate to apply based on the
properties of each data object.
Source: DataTemplateSelector Class
Knowing this - my situation is that I have two types of objects where each object has its own set of data templates it can use. Is there any way I can simply have the content control's ContentTemplateSelector bind to a ContentTemplateSelector property on the view model? The tricky part is that the data templates are defined in the xaml file - I can't just initialized a new instance of the specific ContentTemplateSelector for that class.
Additional info: I have a parent view model where each of its subclasses should be represented as a different type of object. So depending on which subclass view model is toggled, it should use its respective ContentTemplateSelector and data templates.
I've also gotten the above to work with a converter, but I want to stay away from this. Ideally, I'd like to have code that makes this process as general as possible. i.e. Not needing to maintain the converter code to add new types of objects in the future just to return the right DataTemplateSelector. The case should be that anytime a new subclass is added, it'll just work right away.

When to use FindAncestor?

In the image below, why is FindAncestor needed and why is AncestorType not UserControl?
If the UserControl was inside a StackPanel, would AncestorType be StackPanel?
In other words, what does the parent control have to do with binding to the viewmodel.Message? Why is all the other xaml needed in the Binding?
It wouldn't need to specify AncestorType=UserControl, since that's the default context. If you omit the "RelativeSource" parameter, it will bind to the local DataContext.
In this case, the UserControl and the Window it is contained in must have different DataContexts. Since a UserControl generally doesn't know the name of its parent at design time, you can at the least usually assume it's only going to be in a single Window and create a binding to the Window's DataContext using RelativeSource as shown.
This can be common because in an application, the Window might have a DataContext for information about the application as a whole, but the current UserControl might be focused on a particular piece of data (such as an Employee). In this case all the default bindings point to the Employee, but the UserControl might want to bind to something in the parent DataContext too.
Why is FindAncestor needed?
Here FindAncestor is used to access to the Window object to get an access to the DataContext of Window object.
Why is AncestorType not UserControl?
Because the DataContext of the UserControl object may be not the same as the DataContext of Window object.
Normally it's the same but you can redefine it.
If the UserControl was inside a StackPanel, would AncestorType be StackPanel?
No if the StackPanel is itself in your Window.
Don't forget that you target the Type of the graphical object that contain the DataContext you want.
In this case, the developer just knew that the object that had the datacontext they were looking for was a Window. If, for example, a data context was set on a stackpanel and you wanted something from that datacontext, then you would use the AncestorType = Window. Since there are two datacontexts, and the user wanted to bind something to the outside one, FindAncestor was used.

DataContext changes before I can pass parameters

I have a control with a dependency property which I want to pass which is a property in a class, and I also want to use an ObservableCollection which part of that class as the datacontext for that control.
<mycontrols:News
feedStatus="{Binding newsData.newsStore.feedStatus}"
DataContext="{Binding newsData.newsStore.news}"
/>
The problem here is that the DataContext is used when it evaluates {Binding newsData.newsStore.feedStatus} how can I get it to pass feedStatus first and then set the DataContext.
I would use just the single datacontext if silverlight had the ability to back track up the datacontexts parent, but I don't think this is the case.
Could I set datacontext as a nested parameter?
Set the DataContext to DataContext="{Binding newsData.newsStore} and then bind the feedStatus and news properties inside your UserControl.
Alternatively use multiple dependency properties, instead of the DataContext.
Also, please use .NET naming conventions (PascalCase!). Java style casing makes my eyes cringe.

Multiple DataContext in a View vs MVVM? Is that right?

I have the following problem: I'm building a chat WPF application on which I want the user to be connected with different accounts to GTalk. I've made a ViewModel that permits handling the communication but I don't know which is the best way to handle DataContext. I think that I need different DataContexts for every connection instance but I don't know if this is the right way and don't know how to define multiple DataContexts in a View.
A DataContext provides the default binding source for an element in the view. It is inherited from parent to child within the visual tree. You can change the DataContext for any element by binding it to some property of its parent DataContext. This is a common way of creating 'islands' that bind to a child view model.
For example, if you have a User view model that has an Address Property, you can render this in an AddressUserControl as follows:
<StackPanel>
... elements bound to properties of User ...
<AddressUserControl DataContext="{Binding Address}"/>
</StackPanel>
If you have a variable number of accounts, you can use the ItemsControl.
The rough idea behind this: You can bind the ItemsControl to a list of "Sub-ViewModels" in your main ViewModel and define a DataTemplate (= a View) for each of them. The DataContext of each DataTemplate is automatically assigned to a corresponding item in your ViewModel's list.

Categories