I'm a little confused about how the data binding works when using these types.
I've read that you can't do the following
public partial class Window1 : Window
{
public ObservableCollection<string> Items { get; private set; }
public Window1()
{
Items = new ObservableCollection<string>() { "A", "B", "C" };
DataContext = this;
InitializeComponent();
}
}
<Window x:Class="WpfApplication25.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ComboBox>
<ComboBox.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Items}"/>
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
</Window>
because CompositeCollection has no notion of datacontext and so anything inside of it using a binding has to set the Source property. Such as the following :
<Window x:Class="WpfApplication25.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<CollectionViewSource x:Key="list" Source="{Binding Items}"/>
</Window.Resources>
<ComboBox Name="k">
<ComboBox.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Source={StaticResource list}}"/>
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
</Window>
But how is that working? it sets the source to something, but that something, in this case a CollectionViewSource uses a datacontext (as its not explicitly setting a source).
So because "list" is declared in the resources of Window, does that mean it gets Windows DataContext? In which case, why doesn't the following also work?
<Window x:Class="WpfApplication25.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<Button x:Key="menu" Content="{Binding Items.Count}"/>
</Window.Resources>
<ComboBox Name="k">
<ComboBox.ItemsSource>
<CompositeCollection>
<ContentPresenter Content="{Binding Source={StaticResource menu}}"/>
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
</Window>
you are right CompositeCollection
has no notion of datacontext
so it cant inherit it from its parent.
from MSDN:CompositeCollection can contain items such as strings, objects, XML nodes, elements, as well as other collections. An ItemsControl uses the data in the CompositeCollection to generate its content according to its ItemTemplate. For more information about using ItemsControl objects to bind to collections, see the Binding to Collections section of the Data Binding Overview.
to your questionBut how is that working? it sets the source to something, but that something, in this case a CollectionViewSource uses a DataContext (as its not explicitly setting a source).
I guess you over think it, the Collection
DependecyProperty can bind to any IEnumerable
type so it doesn't matter how the collection was created as long as its created and implements IEnumerable
.
in your case the CVS inherits the DataContext from the Window and then binds to Items
.
regarding your second example it doesn't work because the ContentPesenter needs dataContext to work so since it could inherit it, the binding mechanism just set itself as the dataContext even though you tried binding the content Source
to the button, you forgot to set the path, I guess this is why it got ignored.
all you have to do to make it work is just set it like that:
<ContentPresenter Content="{Binding Source={StaticResource menu}, Path=Content}"/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With