WPF MainWindow to display other pages - c#

I am trying to create a Main Window that will have a Header for navigation/buttons, and a footer for displaying information.
(similar to the top and bottom bars on StackOverflow.com)
What is the best way to make the Main Window function as a container that could display any page in between the header/footer?

I would create a 3 row Grid, with the center item being a ContentControl. Bind it to a CurrentPage property on your view model.
Create a Base Page class, and subclass it for each page of data you want to display. This subclass is also the viewmodel for each individual page.
Add a DataTemplate for each subclass of Page for the ContentControl to use, making sure to specify the Type attribute (This is what physically attaches the page type to the UI based on the CurrentPage property). The content of the DataTemplate should be a UserControl that contains the UI for each page type.
Now when you want to change pages, just set CurrentPage to an instance of the page you want, and it will automatically change.
This pattern will keep each page's UI separate from all the other, and gives them a strong view model (the Page subclass). It allows for super easy changing of pages. and follows the MVVM pattern nicely. You can even load all your pages in to a list that you present to the user. With a little more binding the user selecting a page can flow right in to the page change behavior with very little work.

create a page with 3 rows. The top row being a height of 'auto' the middle row being of height '*' and the bottom row being height 'auto' as well. The top and bottom row will take up as much room needed for the header and footer and the middle row will take up the rest of the room.

You can use a Grid
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<local:TopPage Grid.Column="0" Grid.Row="0" />
<local:MidPage Grid.Column="0" Grid.Row="1" />
<local:BottomPage Grid.Column="0" Grid.Row="2" />
</Grid>

Related

Multiple list views - auto height for all of them

I'm trying to resolve some layout problems in my Xamarin.Forms application. For example, when height of content is higher than body content height, then lists will collapse.
I have undefined amount of lists with custom item templates. I want to remain all height of each list and have possibility of scrolling them.
I tried use StackLayout but it doesn't support scrolling. When I use ScrollView, the Auto property doesn't work correctly (there is ambigous space between each of lists).
My code looks like this:
<Grid>
<Grid.ColumnDefinitions>
...
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0"> //Header
...
</Grid>
<StackLayout Grid.Row="1"> //Group of lists
<ListView x:Name="firstList" ItemTemplate="..." ItemsSource="...">
</ListView>
<ListView x:Name="secondList" ItemTemplate="..." ItemsSource="...">
</ListView>
...
</StackLayout>
</Grid>
How can I position these lists on full height?
What you try to achieve is very ambiguous from the mobile app perspective. Think the other way around: While your screen is full of stacked ListViews, how would the system know it has to scroll down the page or scroll down the current ListView?
Also nesting ListView into ScrollView is a very bad practice because:
ListView implements its own scrolling.
ListView will not receive any gestures -> they will be handled by the parent ScrollView.
also ListView can have customized header and footer that scrolls with the elements of the list, potentially offering the functionality that the ScrollView was used for.
If you want to stick to this layout, your option here would be to design your own implementation of your control using custom renderers and manage the gesture.
Hope it helps and happy coding!

Static UI header element needs to remain in view when on-screen keyboard is opened for a RichEditBox

I'm trying to change the behaviour when there's on-screen keyboard presence similar to what is described on https://msdn.microsoft.com/en-gb/windows/uwp/input-and-devices/respond-to-the-presence-of-the-touch-keyboard?f=255&MSPPError=-2147217396 but not actually clarified as to how to achieve:
In some cases, there are UI elements that should stay on the screen
the entire time. Design the UI so that the form controls are contained
in a panning region and the important UI elements are static.
This is my page's basic xaml layout:
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="titlebar" Grid.Row="0" />
<RichEditBox x:Name="content" Grid.Row="1" />
</Grid>
What I want is for the titlebar element to still be visible on-screen when the touch-screen keyboard is opened. At the moment, what's happening is when the on-screen keyboard is called, the page is automatically scrolled down so that the RichEditBox appears at the very top of my view (requiring me to scroll up in order to get the titlebar back into view).
Any guidance on how to achieve the behaviour I'm after will be much appreciated.
Put both header TextBlock and RichTextBox in a Grid and then use translateY on the Grid's transform when RichTextBox receive focus.
Maybe something like this https://social.msdn.microsoft.com/Forums/windowsapps/en-US/99652e87-113c-47fa-a8e7-60f11fc9f160/virtual-keyboard-covering-textbox
http://blog.jerrynixon.com/2013/08/windows-8-xaml-manipulation-using.html?m=1

Visual studio 2015 Properties panel

I'm reading a tutorial about c# wpf projects and at some point it tells me to put a tab control on my project and set its properties like this:
Grid.RowSpan="2" Canvas.Left="10" Canvas.Top="2" Width="408" Height="208" Grid.Row="1"
My novice problem is that I cannot find Grid.RowSpan property on properties panel in order to change it.
Are some properties available only from xaml editor?
Is there a way to find it on properties panel also?
You tabcontrol goes inside the page's grid, so the Grid.RowSpan property is inherited from that.
Additionally, you may have defined some rows in your grid in a way similar to this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
So, basically, that should work. RowSpan is written with Capital "R" and "S" btw, could htat be it?
I'm not entirely sure, but some are definitely easier to use from XAML.
It is in the layout properties (see picture).
Grid.Rowspan in VS Properties

Winrt Xaml Grid ROw not filling Space with *

I have the problem, that my Grid is not filling the space as I want it.
Here some code:
<HubSection>
<Grid Width="850">
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
<RowDefinition Height="*"/>
<RowDefinition Height="310"/>
</Grid.RowDefinitions>
<Input:RadDatePicker Grid.Row="0" Value="{Binding CurrentDate, Mode=TwoWay}" />
<ListView
Grid.Row="1">...
</ListView>
<Grid Height="310"
Grid.Row="2">...
</Grid>
...
I want that the middle row is filling the space up of the hubsection. Instead it now just fills up when the listview contains enough items.
Any idea?
Now the filled ListView:
I would try setting the VerticalContentAlignment of the HubSection to Stretch as well as setting the VCA of the outer grid to that option. I'm suspecting the default might be Center or Top and so the minimizing vertical alignment control from the parent control and the expanding star-sized row setting of the inner grid come in a little bit of a conflict that some layout prioritizing rules probably resolve in getting the VCA rule to win.
For similar layout issues it is usually best to analyze with a visual tree debugger such as the XAML Spy or WinRT XAML Toolkit. You can also try tracing these various properties by walking the visual tree with the VisualTreeHelper class yourself.

WPF Sizing Grid.Row to content

I have a window that uses SizeToContent="WidthAndHeight" and I have a column that has three rows in it. Rows are defines as such:
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
Content is made up of one other Grid panel per above row. Each of those panels contains a label and a ListBox. ListBox dynamically adds or removes its content. So, it might have one item, or it might have 100 items.
My problem is this: When my application starts, the three above-mentioned rows are sized to the content within them. So it looks pretty neat. If the first row contains only one item in the ListBox, it'll size it just enough to fit those items. The other two rows (if overfilled with content) will split the rest of the space in half and make their scroll bars visible if the user wants to see the overflows in each one. However, as soon as I re-size the main window, the three rows will immediately re-size themselves to where each one will be the exact same height, no matter the amount of content in them.
I tried using Height="Auto" in the row definitions of the outer grid; however, that sizes each row to fit the content precisely, thus causing them to overflow off the screen, without ever enabling the scroll bars.
I've tried every setting that I know of (key: know of) and I couldn't solve it. For now I got rid of SizeToContent so that that weird bug wouldn't happen, but the rows are sized proportional to each other no matter the amount of content in them... and I'd like it the other way. I don't want a static height for each of the rows, but rather having them to re-size themselves dynamically, based on the amount of content in them without going off the screen.
Is there a way to fix this?
To get it right you'll have to make your own custom Panel which handles size distribution smarter than the standard Grid. This project may be a good starting point: ConstrainingStackPanel
In your XAML you could bind to a property in your ViewModel
<Grid.RowDefinitions>
<RowDefinition Height="{Binding Row1Height}"/>
<RowDefinition Height="{Binding Row2Height}"/>
<RowDefinition Height="{Binding Row3Height}"/>
</Grid.RowDefinitions>
Then in your ViewModel
public int Row1Height { get; set; }
public int Row2Height { get; set; }
public int Row3Height { get; set; }
And have some calculation that populates that value once you have content.
Assuming I understand your question correctly, have you tried wrapping it inside of a ScrollViewer and turning the scollbar off for the ListView?
I've found that layout rendering in WPF can be both a positive and a crutch. It's sometimes a pain in the butt to get it to work right when it comes to content sizing.
If a ScrollViewer is not an approach you'd like to take, you could easily accomplish something like this through writing some sort of attached behavior (I've done this in the past) but in this case it's way overkill.
Example of ScrollViewer approach:
<Grid>
<ScrollViewer>
<ListView ItemsSource="{Binding Something}" ScrollViewer.VerticalScrollBarVisibility="Hidden">
:
:
:
</ScrollViewer>
</Grid>

Categories

Resources