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

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

Related

Binding doesn't work on DependencyObject created in XAML

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

WPF and MVVM: bind UserControl to XAML dynamically

seems like a trivial task: i am building a wpf application, using MVVM pattern. what i want is dynamically change part of a view, using different UserControls, dependent on user input.
let's say, i have got 2 UserControls, one with a button, and another with a label.
in main view i have a container for that. following XAML "works":
<GroupBox Header="container" >
<local:UserControlButton />
</GroupBox>
and a UserControl element with buttons pops up. if i change it to another one, it works too.
question is how to feed that groupbox dynamically. if i put something like that in my model view:
private UserControl _myControl;
public UserControl MyControl
{
get
{
return _myControl;
}
set
{
_myControl= value;
InvokePropertyChanged("MyControl");
}
}
and change my view XAML to something like:
<GroupBox Header="container" >
<ItemsControl ItemsSource="{Binding MyControl}" />
</GroupBox>
and feed it from command with usercontrol for button or for label: nothing happens, although "MyControl" variable is set and is "invoke property changed"..
Obviously there are many ways to skin this particular cat - but to answer the question of why it doesn't work you need to look into the ItemsSource property of ItemsControl on MSDN.
The items control is designed to show multiple items, provided through an IEnumerable passed to the ItemsSource property. You are passing a UserControl, so the binding will fail.
For your example, I would change the ItemsControl to a ContentControl and bind the content to your MyControl property. This should then work.
<GroupBox Header="container" >
<ContentControl Content="{Binding MyControl}" />
</GroupBox>
However, I would strongly recommend looking into other ways of doing this - having a control in your VM breaks MVVM to my mind. Depending on what you are doing look at data templates - #Sheridan's link in the comments provides an great description of a way to do it.
Couldn't post this as a comment so adding as answer..
Have a look at this:
Implementing an own "Factory" for reusing Views in WPF
It uses DataTemplates but doesn't require the DataTemplate section for each view. If you potentially have a lot of user controls/views you wish to display or you are reusing through multiple views or you are intending to actually dynamically generate a view (versus just loading an existing user control) then this might suite your needs.

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.

C# MVVM DataGrid Binding Strategies?

What is the difference between:
<DataGrid
ItemsSource="{Binding MyCollection}"
/>
and...
<CollectionViewSource x:Key="CollectionData" Source="{Binding MyCollection}"/>
...
<DataGrid
DataContext="{StaticResource CollectionData}"
ItemsSource="{Binding}"
/>
They both seem to work. The only difference is that the second snippet, I can't bind to the SelectedItem. So why would someone pick one strategy over the other? Why wouldn't someone just use the first snippet? Thanks.
MSDN states...
CollectionViewSource has a View
property that holds the actual view
and a Source property that holds the
source collection.
CollectionViewSource seperates the actual collection from the view that is representing the collection. This give you the ability to change the visual structure of the visible collection (think filtering out certain items as you type) without actually changing the underlying collection. It is a wrapper around the actual collection containing the objects needing a visual representation. Bea has a great article about it.
In addition you'll notice the explicit wrapping taking place in the CollectionViewSource in your second example...
Source="{Binding MyCollection}"
Then the CollectionViewCource is now being bound to via the DataGrid providing the seperation I mentioned earlier; whereas the collection was being bound to directly in your first example.
A CollectionViewSource has more features that an ObservableCollection or whatever IEnumerable you use for your ItemsSource. For example, it has SortDescriptions that can allow you to group data. An example can be found here.
TLDR; its a more powerful data structure.
As an aside, provided IsSynchronizedWithCurrentItem is true on the DataGrid, you can bind to the SelectedItem by appending a slash i.e. {Binding /}

Is there an MVVM-friendly way to swap views without value converters firing unnecessarily?

I thought what I was doing was right out of the Josh Smith MVVM handbook, but I seem to be having a lot of problems with value converters firing when no data in the view-model has changed.
So, I have a ContentControl defined in XAML like this:
<ContentControl Grid.Row="0" Content="{Binding CurrentViewModel}" />
The Window containing this ContentControl references a resource dictionary that looks something like this:
<ResourceDictionary ...>
<DataTemplate DataType="{x:Type lib_vm:SetupPanelViewModel}">
<lib_v:SetupPanel />
</DataTemplate>
<DataTemplate DataType="{x:Type lib_vm:InstructionsPanelViewModel}">
<lib_v:InstructionsPanel />
</DataTemplate>
</ResourceDictionary>
So, basically, the two data templates specify which view to show with which view-model.
This switches the views as expected whenever the CurrentViewModel property on my window's view-model changes, but it also seems to cause value converters on the views to fire even when no data has changed. It's a particular problem with IMultiValueConverter classes, because the values in the value array get set to DependencyProperty.UnsetValue, which causes exceptions unless I specifically check for that. But I'm getting other weird side effects too.
This has me wondering if I shouldn't just do everything manually, like this:
Instantiate each view.
Set the DataContext of each view to the appropriate view-model.
Give the ContentControl a name and make it public.
Handle the PropertyChanged event for the window.
In the event handler, manually set the Content property of the ContentControl to the appropriate view, based the CurrentViewModel (using if statements).
This seems to work, but it also seems very inelegant. I'm hoping there's a better way.
Could you please advise me the best way to handle view switching so that value converters don't fire unnecessarily?
You should look at PRISM or any other composite UI framework. Prism will give you a great mechanism for this type of thing.
I solved this by getting rid of all IValueConverter and IMultiValueConverter classes and just using the ViewModel to provide all data. It turns out, this requires less code and hassle, and doesn't sacrifice anything that I'm aware of.

Categories