How to bind to parent DataTemplate from within an ItemsControl.ItemTemplate - wpf

I have a container type control which contains a number of items. The container control has a DataTemplate defined which also contains a ItemsControl with a DataTemplate for the item. The items however need to bind to something from the container control. A simplified example is given below:
<DataTemplate DataType="{x:Type ContainerType}">
<!-- Display of the container stuff-->
<ItemsControl ItemsSource="{Binding Items, Mode=OneWay}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type Item}">
<!-- Display of the item stuff -->
<ComboBox Text="Choose a container-level option..."
ItemsSource="{WHAT GOES HERE?}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
How to I bind something at the item level back up to the container level?

You can use a RelativeSource binding
<ComboBox ItemsSource="{Binding SomeCollection,
RelativeSource={RelativeSource
AncestorType={x:Type local:MyContainerControl}}}"/>
What you use for your binding path depends on where the collection is located. If it is located as a DependencyProperty on MyContainerControl, then the above binding works fine. If it is located in the DataContext of MyContainerControl, then you'll need to set the binding path to DataContext.SomeCollection

Maybe use TemplateBinding?
Something like:
{TemplateBinding YourPropertyInTheDataTemplateContext}

I've always been a big fan of ElementName. Basically you make sure you name the outer level control like : x:Name="MainWin" and then you can do something like this:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ComboBox ItemsSource="{Binding ElementName=MainWin, Path=DataContext.SomeCollection}"/>

Related

Binding to two dependency properties of the user control which is a ListViewItem

I've created an user control which is a ListViewItem. That control has 2 dependency properties I would like to bind to from my ViewModel. But how am I supposed to do that when I can only bind one thing (collection) to ListView ItemsSource property? How can I bind to ExpanderInfo dependency property? Is there any way to do that or maybe I have made a bad assumption and should have created user control in other way?
Here is my xaml code:
<ListView ItemsSource="{Binding Tasks}" SelectedItem="{Binding SelectedTask}" Height="200" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<tc:TaskTile TaskInfo="{Binding}" ExpanderInfo="{Binding ExpanderStatus}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
Thank you for your help!
Replace <tc:TaskTile TaskInfo="{Binding}" ExpanderInfo="{Binding ExpanderStatus}"/> with
<tc:TaskTile TaskInfo="{Binding}" ExpanderInfo="{Binding DataContext.ExpanderStatus, RelativeSource={RelativeSource AncestorType=ListView, Mode=FindAncestor}}"/>

WPF bind to collection of controls

I want to do a binding to a collection of homemade custom controls.I've a collection of objects (called Parameters), each one of these should be presented in a panel by a custom control.
I have the following in my main window:
<ItemsControl Grid.Column="1"
ItemsSource="{Binding Path=Parameters}">
</ItemsControl>
And I have a resource file to declare how to view each Parameter object:
<DataTemplate DataType="{x:Type path:Parameter}">
<Grid>
<myControls:MyUserControl
Parameter="{Binding RelativeSource={RelativeSource Self}}">
</myControls:MyUserUserControl>
</Grid>
</DataTemplate>
My control takes a Parameter so I want to bind it to itself for every item in the collection. How can I do that binding?
In a DataTemplate that serves as ItemTemplate in an ItemsControl, the DataContext holds the individual items of the source collection. Hence the binding should look like this:
<myControls:MyUserControl Parameter="{Binding}" />
and the ItemsControl may be written like this to explicitly use the DataTemplate:
<ItemsControl ItemsSource="{Binding Path=Parameters}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<myControls:MyUserControl Parameter="{Binding}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Relative Binding in Silverlight

I have an ItemsControl in my application. The page associated with the ItemsControl is bound to a view-model. The view-model includes two properties: People and Options. For each person, I want to display a list of options in a ComboBox. The options are defined in my view-model. My code looks like the following:
<ItemsControl ItemsSource="{Binding Path=People}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ComboBox ItemsSource="Options" DisplayMemberPath="FullName" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
However, because each Item represents a Person, the ComboBox is looking at the Person object for a property called "Options". How do I reference the view model for the from the ComboBox instead of the Person?
Thanks!
You can use the following technique
<ComboBox ItemsSource="{Binding ElementName=LayoutRoot, Path=DataContext.Options}" DisplayMemberPath="FullName" />
Assuming that your LayoutRoot's DataContext is the View Model. If not you can give your ItemsControl a name and use that for the ElementName.

Binding a WPF ComboBox to a different ItemsSource within a ListBox DataTemplate

I have a ListBox that contains a textbox and a combobox in its datatemplate:
<ListBox Height="147" Margin="158,29,170,0" Name="PitcherListBox" VerticalAlignment="Top" ItemsSource="{Binding SomeCollectionOfObjects}" Background="Black">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Path=Name}" />
<ComboBox ItemsSource="{Binding LocalArrayOfIntsProperty}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I want to bind the listbox to a collection of objects (which I've done successfully), but I want the combobox in the above datatemplate to have its itemssource set to a local property on the window (array of ints). I still want the combobox to have a two-way bind between its selected item and a property on the collection of objects...
I have the following in code:
PitcherListBox.DataContext = this;
Basically in the end, I want the combobox within the listbox to have a different itemssource than the listbox itself. I can't seem to figure out how to change the ComboBox's ItemsSource in XAML. Can someone provide me some feedback? Thanks!
Try this:
<ComboBox ItemsSource="{Binding LocalArrayOfIntsProperty, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type YourWindowTypeHere}}}" />
Note that you need to replace YourWindowTypeHere with the type of the Window containing the LocalArrayOfIntsProperty! Also remember that you will need to define an xml namespace for that type!

WPF Multiple master/details, same grid

I have a TreeView which has three levels.
Lets say its a league, division and team TreeView.
Now, when I select each of the items in the tree, I would like to see detailed information about it.
Whats the best way to achieve this?
Since Grid doesn't items (like a ListBox), I can't just set its ItemsSource and make a DataTemplate...
I thought about using a ListBox which will contain only the selected item but this seems to be very bad...
Thanks.
You first define the 3 DataTemplates for your league, division and team classes. After, you bind the TreeView to the root of your objects. Your League and Division classes should have a Children property that returns the children. All your classes should have a Name property.
Then when you want to show a single object, use the ContentPresenter, and the bind its content to the SelectedItem if the TreeView.
For example:
<StackPanel>
<StackPanel.Resources>
<DataTemplate DataType="{x:Type your_namespace:League}">
<StackPanel Orientation="Vertical">
<TextBlock Text={Binding Name}/>
<.../>
<StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type your_namespace:Division}">
<StackPanel Orientation="Vertical">
<TextBlock Text={Binding Name}/>
<.../>
<StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type your_namespace:Team}">
<StackPanel Orientation="Vertical">
<TextBlock Text={Binding Name}/>
<.../>
<StackPanel>
</DataTemplate>
</StackPanel.Resources>
<TreeView x:Name="_tree" ItemsSource="{Binding RootOfYourItems}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text={Binding Name}/>
</HierarchicalDataTemplate>
</TreeView>
<ContentPresenter Content="{Binding Path=SelectedItem, ElementName=_tree}" />
</StackPanel>
This code was not tested or compiled, it just provided as an example.
I would create a viewmodel with properties for the tree structur, the current selection and the details to the current selection.
The tree struct is one-way bound to the treeview, the SelectedItem from the treeview is OneWayToSource bound to the current selection property (due to the limitations of the property). This property changes the list of child items once the current selection changes, and the child items are bound to the listbox displaying them.

Resources