Design with multiple Expanders - c#

I need a little help in creating the design I want.
My ViewModel has three collections which are bound to three ItemsControls using Caliburn.Micro. Each collection contains between 10 and 31 items.
I want to put each ItemControl into an Expander. So far, so simple:
<StackPanel>
<Expander IsExpanded="True" Header="Day recordings">
<ItemsControl Name="DayRecordings" />
</Expander>
<Expander IsExpanded="False" Header="Month recordings">
<ItemsControl Name="MonthRecordings" />
</Expander>
<Expander IsExpanded="False" Header="Digit recordings">
<ItemsControl Name="DigitRecordings" />
</Expander>
</StackPanel>
The problem now is that they expand beyond the bounds of the StackPanel they are contained in.
I would like the Expanders to behave like this:
If only one Expander is expanded, it should use the complete space of the StackPanel minus the space needed for the other, not-expanded Expanders. Inside the expanded Expander a vertical ScrollBar should be shown.
If N Expanders are expanded, each should take 1/Nth of the total space of the StackPanel minus the space needed for the other, not-expanded Expanders. In each of the expanded Expanders a vertical ScrollBar should be shown.
If one of the expanded Expanders needs less space than the assigned 1/Nth, it should only use the needed space and the excess space should be evenly distributed to the other expanded Expanders. This behavior is nice-to-have but not essential
Unfortunately, I don't have more than the simple XAML from above, because I don't even have an idea on how to tackle this...

Use a ScrollViewer, put a Grid in it, set row heights to auto.
Put a converter on MaxHeight if you want some fancy layout.

Use the accordion control from the toolkit to get the required behavior.

Related

WPF Scrolling AutoSizing Panel

I have a WPF application in which the main window holds a DockPanel with two children. The top child is another DockPanel which holds the menu and is of a fixed size. The lower child is the main work area, which should fill the remaining space and be resizable along with the window. (Hence the DockPanel parent.) Draggable objects get placed in this work area and might appear anywhere inside it.
I'm trying to figure out how to make scroll bars appear if an object is dragged outside the visible area.
The approximate XAML structure currently goes
<Window>
<DockPanel>
<DockPanel with fixed-size content ... >
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid ClipToBounds="True" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"/>
</ScrollViewer>
</DockPanel>
</Window>
So far I've tried a Grid and a Canvas. Both have built-in scroll bars, but they won't appear unless dimensions are specified--but if I apply dimensions, then the panel won't automatically resize to fill the work area.
Then I tried surrounding the panel with a ScrollViewer. The unconstrained panel now successfully auto-resizes to fill the space, but the ScrollViewer has the same problem as the panel--it will only display scroll bars if it's constrained to hard dimensions.
I'm thinking that this would work if I could dynamically constrain the ScrollViewer. So far, I haven't found any reliable way to dynamically apply size values to the ScrollViewer.
Is there a way to create a Binding between the ScrollViewer dimensions and the ActualHeight and ActualWidth of the Grid? Or, is there a way I can define the ActualHeight/ActualWidth of the grid as a DynamicResource that can be applied to the ScrollViewer? Or is there some other panel or method or resource that can be used so that all three criteria (panel fills available space, panel auto-resizes with window, anything dragged outside visible area triggers scroll bars) are met?
Thanks in advance for any help.
The problem was that I did not have a DockPanel.Dock setting on the bottom child of the containing DockPanel. Relying on the DockPanel's LastChildFill wasn't enough to do the job. Once I set DockPanel.Dock = Bottom on the bottom child, the scroll bars started working.

WrapPanel behavior within ListBox: vertical to fill available space and then wrap horizontally

I have a listbox within a custom scrollviewer that provides some unique visual styles. The Listbox ItemsPanel is a WrapPanel, and all of the listbox items are 100x100. The Listbox height is static and will not be changed. The desired layout is this: fill available space vertically before wrapping like so:
I've played with both Orientation variables of the WrapPanel, and have not been able to achieve the desired layout. I suspect this has something to do with the fact that I'm wrapping the Listbox in a custom ScrollViewer control and the listbox can't calculate available space properly. Since the height is static, I feel like i should be able to make this work (it only scroll horizontally, and the outer custom scrollviewer should be doing the scrolling). Here is the current setup slimmed down:
<controls:CustomScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Hidden">
<controls:CustomScrollViewer.Template> .... </controls:CustomScrollViewer.Template>
<ListBox Height="...">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate> .... </DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}"> .... </Style>
</ListBox.Resources>
</ListBox>
</controls:CustomScrollViewer>
Instead of wrapping the Listbox in a scrollviewer, is there a way to get the ListBox to use the custom scrollviewer internally? Or how can I achieve the desired layout?
By hard-coding the Height of the WrapPanel, with the Orientation set to Vertical, I was able to achieve the desired layout.
I would still be curious to a solution that uses the custom scrollviewer to replace the scrollviewer that would be internally in the listbox.

I'm having trouble positioning elements in a Grid when the window is resized

I have a 50x50 draggable grid inside another grid that I am able to move around with the cursor. (I forgot that I am using the DraggableExtender class
The problem is that I want the moveable grid to be relatively positioned inside it's container grid no matter how the container grid is resized. My solution right now is to dynamically change the HorizontalAlignment and VerticalAlignment of the moveable grid whenever it is moved, but this is hacky and doesn't work well.
Relative positioning in a grid is one of the easiest things to do in XAML, but not when you have draggable elements ;(
Any ideas?
EDIT for code and images:
My XAML:
<Grid Margin="10" ClipToBounds="True" Background="#FFB4B4B4">
<Grid Name="testGrid" MouseLeftButtonDown="testGrid_MouseLeftButtonDown" MouseLeftButtonUp="testGrid_MouseLeftButtonUp" RenderTransformOrigin="0.5,0.5" Height="100" Margin="50,0,0,0" Width="100" Background="#FFE6E6E6" local:DraggableExtenderGrid.CanDrag="true" HorizontalAlignment="Center"/>
</Grid>
and I use a DraggableExtender class (shown here) which I have edited to apply to a Grid instead of a Canvas (I was hoping for better results from a grid.. but both containers produce the same result, even with the original class on a canvas).
This is a picture of my 2 grids. I can move the smaller grid around inside it's parent grid, but I would like for it to maintain relative positioning once the window is resized. This is what it currently looks like when I resize the window. In this particular example, the grid would ideally remain slightly off-center horizontally and vertically in both pictures.
May be you should try placing the Grid inside a Canvas instead..
Take a look here

Windows Phone 8 ScrollViewer.CanContentScroll not recognized?

I am a newbie to Windows Phone 8 app programming in C# and I am trying to create an array of textboxes. I have the array being created and being added as children of a Stack Panel, and I am trying to get it to display more than a few textboxes, and I read that it can be done if the CanContentScroll property is set to 'true' as it is set to 'false' by default. However, when I try to add it, it is not recognised by intellisense. Can you help me?
<ScrollViewer VerticalScrollBarVisibility="Auto" CanContentScroll="True" Margin="10,135,10,7" >
<StackPanel x:Name="TextBoxStack" HorizontalAlignment="Left" Height="419" Margin="0,166,0,0" VerticalAlignment="Top" Width="446"/>
</ScrollViewer>
I am using VS2013, and the System.Phone.Controls and System.Windows.Controls modules are included correctly.
Use a Grid and not a StackPanel. I forget the exact reason, but the StackPanel doesn't correctly report it size to the ScrollViewer container causing the ScrollViewer to not scroll correctly. Using a Grid will resolve this.
You shouldn't need to set "CanContentScroll". The ScrollViewer should display scroll bars if its child extends further than the ScrollViewer's bounds. Try:
Remove the fixed height of the child StackPanel. You don't want to restrict its height -- it should extend as far as its children, so that the ScrollViewer knows the correct scroll extent.
Make sure the ScrollViewer has a fixed or limited height -- ie, put it inside a fixed-size container like Grid, rather than an infinitely-extendable one like StackPanel. If it can extend infinitely, it will always be able to accommodate its child, and won't ever think it has to scroll.
Eg:
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel x:Name="TextBoxStack"
HorizontalAlignment="Left" VerticalAlignment="Top" Width="446"/>
</ScrollViewer>
</Grid>

ListBox with Stackpanel-Items - How to enable scroll? WPF

I'd like to enable a ScrollView for my ListBox. My ListBox is showing StackPanels.
Unfortunately I'm not able to set a specific height to my ListBox (this is the only solution I found where I can use my Scroller).
What do I have to do to get a ScrollBar for my ListBox? (And even if I minimize/maximize the window it should appear if necessary)...
Thanks
Well, the ListBox in WPF already contains a scroll, which you can force to be visible like this:
<ListBox
ScrollViewer.VerticalScrollBarVisibility="Visible">
</ListBox>
Most probably your problem comes from the fact, that your listbox resides in a control, which does not delimit it's height, so your listbox has a height that is exactly equal to the needed space (which may be more than your screen estate). Try to put it inside a Grid for example.
So to illustrate it with an example:
<StackPanel>
<ListBox>
<ListBox.Items>
<TextBlock>Test</TextBlock>
...
</ListBox.Items>
</ListBox>
</StackPanel>
will never show a scrollbar, as the stackpanel will have a height that will be always enough for the listbox to show all elements, even though it might not be visible on the screen.
But if you switch the StackPanel to a Grid in the above example you will have scrollbars when they are needed, as the Grid will constrain the height of the child control (the ListBox).
Hope this helps.

Categories

Resources