How to override the ItemsSource defined for an ItemTemplate? - wpf

I use an Item Template to define how the rows of my grid must be displayed. The grid definition (simplified) shows that the item template source is GridRows (a collection of rows) :
<grid ...>
(...)
<ScrollViewer
ItemTemplate="{StaticResource GridRowItemDataTemplate}"
ItemsSource="{Binding GridRows}" />
</ScrollViewer>
</grid>
So far, so good.
In the item template, the textbox is bound to ImportZoneName, which resolved of course to GridRows[i].ImportZoneName, and this is exactly what I want :
<DataTemplate x:Key="GridRowItemDataTemplate">
<Grid>
<TextBlock {Binding ImportZoneName}" />
<ComboBox
SelectedItem="{Binding SelectedModelingTypeValue}"
ItemsSource="{Binding ModelingTypes}" />
</Grid>
</DataTemplate>
Now the problem : I also want to bind the combo box to an other property (ModelingTypes) of my view model. This property is not linked in any way to GridRows. How can I tell WPF to override (or forget) the item template source?
Many, many thanks !
BTW, I did not find yet a simple guide for these simple binding cases... If anyone have a link to such a guide, I will bless him/her forever :)

You can get the DataContext of the parent list like this:
<DataTemplate x:Key="GridRowItemDataTemplate">
<Grid>
<TextBlock {Binding ImportZoneName}" />
<ComboBox
SelectedItem="{Binding SelectedModelingTypeValue}"
ItemsSource="{Binding DataContext.ModelingTypes,
RelativeSource={RelativeSource FindAncestor,
AncestorType=Grid}}" />
</Grid>
</DataTemplate>
Replace Grid with the type of the grid you are using (not sure which it is, not evident from the question), as long as its DataContext has the property ModelingTypes

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}}"/>

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

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}"/>

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.

WPF : How to create separate Resources for each item in a bound ItemsControl

I want to achieve the following:
My ViewModel exposes a property named 'Categories' which is a collection of CategoryViewModel objects
Each CategoryViewModel object exposes a property called 'Items' which is a collection of strings*.
On my View, I want a TabControl with a TabItem for each object in the 'Categories' collection.
The Content of each TabItem should be a xceed DataGrid control displaying the contents of the selected tab's Items collection.
<TabControl ItemsSource="{Binding Categories}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding CategoryName}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<xcdg:DataGridControl
ItemsSource="{Binding Items}"
AutoCreateColumns="True">
</xcdg:DataGridControl>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
This works ok when I bind directly to the ItemsSource property of the DataGridControl. However, in order to utilize all of the functionality of the DataGridControl, I need to bind the ItemsSource property of the DataGridControl to a DataGridCollectionViewSource object that is bound to my Items collection. I do this when the grid ISN'T nested in another control by creating a DataGridCollectionViewSource object in the Resources section of the UserControl and binding to that.
<UserControl>
<UserControl.Resources>
<xcdg:DataGridCollectionViewSource x:Key="GridData"
Source="{Binding Items}" />
</UserControl.Resources>
<Grid>
<xcdg:DataGridControl
ItemsSource="{Binding Source={StaticResource GridData}}"
AutoCreateColumns="True">
</xcdg:DataGridControl>
</Grid>
</UserControl>
How do I need to structure the XAML so that when the TabControl is being bound, a DataGridCollectionViewSource object is created for each TabItem so that the DataGridControl that is generated within the content of the TabItem can be bound to it?
Clear as mud, right? :)
Thanks!
Notes:
*In the real solution the collection contains objects of a class that is more complex than a simple string, but a string was used to make the example more simple.
OK, this is a bit of a long-shot, but could you use the DataGrid.Tag ...
<TabControl.ContentTemplate>
<DataTemplate>
<xcdg:DataGridControl
ItemsSource="{Binding RelativeSource={RelativeSource Self}, Path=Tag}"
AutoCreateColumns="True">
<xcdg:DataGridControl.Tag>
<xcdg:DataGridCollectionViewSource x:Key="GridData"
Source="{Binding Items}" />
</xcdg:DataGridControl.Tag>
</xcdg:DataGridControl>
</DataTemplate>
</TabControl.ContentTemplate>
Or ... resources can be defined on any FrameworkElement, so you could try:
<TabControl.ContentTemplate>
<DataTemplate>
<xcdg:DataGridControl
ItemsSource="{Binding Source={StaticResource GridData}}"
AutoCreateColumns="True">
<xcdg:DataGridControl.Resources>
<xcdg:DataGridCollectionViewSource x:Key="GridData"
Source="{Binding Items}" />
</xcdg:DataGridControl.Resources>
</xcdg:DataGridControl>
</DataTemplate>
</TabControl.ContentTemplate>
I don't use the eXceed Grid so cannot test whether these work - just a couple of ideas to try!
Colin E.
You can use x:Shared="True" attribute on a resource. That means a new instance is created for every use of that resource.
Example:
<UserControl.Resources>
<xcdg:DataGridCollectionViewSource x:Key="GridData"
x:Shared="False"
Source="{Binding Items}" />
</UserControl.Resources>

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!

Resources