How to bind multiple ViewModels into Expanders using Caliburn.Micro? - wpf

I have a XAML view that should hold instances of other views and those views should be displayed in a list, each contained in its own Expander. I'm using Caliburn.Micro and MEF to set all the components up.
The ItemsControl itself works just fine (shows the content of the view correctly):
<ItemsControl ItemsSource="{Binding CursorTools}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl cal:View.Model="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
But when I set the ItemsControl's DataTemplate to be an Expander, the Caliburn no longer "finds" the view for the viewmodel (so the expander is empty):
<ItemsControl ItemsSource="{Binding CursorTools}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--<ContentControl cal:View.Model="{Binding}" />-->
<Expander Header="{Binding Path=Title}">
<Expander.ContentTemplate>
<DataTemplate>
<ContentControl cal:View.Model="{Binding}" />
</DataTemplate>
</Expander.ContentTemplate>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The problem is that I will have many items and their content will be large enough to fill the screen, so how can I get the Expander to set its content properly?

Expander is actually a ContentControl so this should work:
<Expander Header="{Binding Path=Title}" cal:View.Model="{Binding}" />

Related

TabControl which is bound to an ObservableCollection MVVM

I am currently working on a project using MVVM pattern and can't find anywhere a solution how to bind an ObservableCollection to a TabControl which has a template for an item of it.
For example, this is where I got so far:
<TabControl ItemsSource="{Binding ConnStringBufferOC}">
<TabControl.ItemTemplate>
<DataTemplate>
<Grid>
<TextBox Text="{Binding Username}"/>
<!-- Controls here -->
</Grid>
</DataTemplate>
</TabContro.ItemTemplate>
</TabControl>
This however only partialy works. It creates controls in the tab header area instead of the tab content area. I would want to bind each item to a new tab which has a header of a bound source from OC, for example:
Header="{Binding Name}"
And in the content area of each tab I would like to have controls, which have contents bound from the ObservableCollection in this example ConnStringBufferOC. So every tab has same controls only content bound to the controls is different.
You need to specify ContentTemplate for tab content and ItemTemplate for tab header
<TabControl ItemsSource="{Binding ConnStringBufferOC}">
<TabControl.ContentTemplate>
<DataTemplate>
<Grid>
<TextBox Text="{Binding Username}"/>
<!-- Controls here -->
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>

Dynamically adding controls to View from MVVM

In WPF, I am using the MVVM model.
I have a View with a Dockpanel and I want to add dynamically StackPanels with a Label and TextBox for all Harddisks found over the Binding.
Therefore my XAML looks like:
<DockPanel Grid.Row="1" HorizontalAlignment="Stretch" Margin="5">
<ItemsControl ItemsSource="{Binding Harddisks}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel DockPanel.Dock="Right" HorizontalAlignment="Right" Margin="2.5,0,0,0">
<Label Content="{Binding Path=Label}" />
<TextBox Text="{Binding Path=GB_Free}" Width="100" IsReadOnly="True"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
It should be four Labels and TextBoxes, but only the first Label and TextBox are shown.
Why?
Your items in your ItemsControl are not actually direct children of the DockPanel. You need to change the ItemsControl to specify that the DockPanel is the Panel. The following will cause the ItemsControl to create a DockPanel and place all the items inside it (rather than the StackPanel that ItemsControl uses by default).
More Info: MSDN: ItemsControl.ItemsPanel Property
<ItemsControl ItemsSource="{Binding Harddisks}">
<ItemsControl.ItemsPanel>
<DockPanel Grid.Row="1" HorizontalAlignment="Stretch" Margin="5" />
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel DockPanel.Dock="Right" HorizontalAlignment="Right" Margin="2.5,0,0,0">
<Label Content="{Binding Path=Label}" />
<TextBox Text="{Binding Path=GB_Free}" Width="100" IsReadOnly="True"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Display list of usercontrols within itemtemplate next to other controls

I would like to display a list of usercontrols binded to a listbox
next to each usercontrol there should be a button
<ListBox ItemsSource="{Binding usercontrollist}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!--usercontrol of the current binded items-->
<Button Content="x" HorizontalAlignment="Right"></Button>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
How can i do this in xaml code
Assuming usercontrollist is a collection of UserControl, then you should be able to do this:
<ContentControl Content="{Binding}" />

Can the groups of a grouped CollectionView be presented horizontally?

I'm implementing a ListBox whose ItemsPanel is a WrapPanel as per this answer, but there's a twist: my ItemsSource is a grouped CollectionView. With a GroupStyle applied to my ListBox, the wrapping shown in that question doesn't work: the groups are always displayed vertically.
Snooping on my app, here's why:
As you can see, the WrapPanel, defined as my ListBox's ItemsPanelTemplate, appears in the ItemsPresenter within each GroupItem; an implicit, vertically-oriented StackPanel (top item in the pink box) is created to contain the GroupItems themselves.
Is there a way to override this behavior, so the GroupItems are placed in a WrapPanel? Would I have to re-template the entire ListBox?
Update: To illustrate what I'm actually doing with my ListBox and the CollectionView grouping, let me post a little XAML:
<Grid>
<ListBox ItemsSource="{Binding}"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
SelectionMode="Multiple"
ItemContainerStyle="{StaticResource itemStyle}">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type WpfApplication1:Item}">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" FontSize="10"/>
<TextBlock Text="{Binding Amount, StringFormat={}{0:C}}" FontSize="10"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
The GroupStyle is at the heart of it: if you remove that, the GroupItems don't get rendered, and the WrapPanel (which you can see appearing beneath the GroupItem in the screenshot above) appears in place of (StackPanel) 98 in the screenshot.
This behavior only seems to occur if you have defined a HeaderTemplate in the GroupStyle.
It can be corrected by setting the GroupStyle.Panel property to contain a WrapPanel:
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<WrapPanel></WrapPanel>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ListBox.GroupStyle>
It will look something like this:
You should be able to replace the group style from the items control (ListBox):
<ListBox.GroupStyle>
<Style />
<ListBox.GroupStyle/>
Or, you should also be able to create a DataTemplate based on the group item object:
<DataTemplate DataType="{x:Type GroupItem}">
<Panel />
</DataTemplate>

Can't access item in ItemsControl

I define my ItemsControl that contain RadioButtons.
I want to access the Items contained in ItemsControl that are attached as binding child - and when I try to access the ItemsControl.Items I can't see the RadioButtons.
The code:
<ItemsControl Name="itemsControl" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding Key}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This is because you are setting the ItemTemplate of the control, ant not its items. To add items do it like this:
<ItemsControl Name="itemsControl" >
<ItemsControl.Items>
<RadioButton Content="{Binding Key}" />
</ItemsControl.Items>
</ItemsControl>

Resources