Extra rows in WPF Data Template - c#

Extra rows in WPF DataTemplate Specification
This seems to be a really good overview of WPF Data Binding from Microsoft: https://learn.microsoft.com/en-us/dotnet/framework/wpf/data/data-binding-overview
The page has links to a PDF download (which seems more comprehensive than the page itself): https://learn.microsoft.com/en-us/dotnet/opbuildpdf/framework/wpf/data/toc.pdf?branch=live and a sample application: http://go.microsoft.com/fwlink/?LinkID=163703.
Question:
In the sample application file: DataBindingLabApp.xaml (~ line 50) a data template is defined for individual list items. The template specifies 4 rows but only two rows are used... Is there a good reason for having unused rows?
<DataTemplate DataType="{x:Type src:AuctionItem}">
<Border BorderThickness="1" BorderBrush="Gray"
Padding="7" Name="border" Margin="3" Width="500">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/> <!-- not needed? -->
<RowDefinition/> <!-- not needed? -->
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
...
I deleted 2 of the rows and as far as I can tell (by comparing screen shots) the extra rows make no difference to the appearance of the list items. Is there any reason they should be retained? The only thing I can think of is for some future functionality (but that seems like a poor practice, no?)

Is there any reason they should be retained?
Unless there are any items in the Grid that sets the Grid.Row attached property to either 2 or 3 you could remove them unless you want the top two (the only two) rows to fill only 50% of the Grid's total height.
A RowDefinition has a default height of Auto which means that the available space will be divided equally among the number of <RowDefinition/> elements that you define.
...as far as I can tell (by comparing screen shots) the extra rows make no difference to the appearance of the list items. Is there any reason they should be retained?
No.
The only thing I can think of is for some future functionality (but that seems like a poor practice, no?)
Yes, then you might as well add them later.

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!

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>

Smooth scrolling within two listbox

I have a two stacked listboxes with data(first ListBox contains <10 elements, second may have up to 5000 elements),the elements of first listbox must be at top:
<ScrollViewer >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Listbox IsScrollable="False"/>
<Listbox Grid.Row="1" IsScrollable="False"/>
</ScrollViewer >
How I can improve perfomance of scrolling?
I know that I've lost virtualizingPanel when I call " ScrollViewer.SetVerticalScrollBarVisibility(sender as ListBox, ScrollBarVisibility.Disabled);"
But is there any way to enable it when I need two ListBoxes?
Why you don't want to use just one ListBox and set different Templates for different Data Types? You will not need to do any additional work to improve performance of scrolling.
Check this MSDN article Data Templating Overview, you will find one of the latest samples uses DataTemplateSelector and SL doesn't have this class, but you can find a lot of blog posts which trys to solve this problem in SL/WP: Implementing Windows Phone 7 DataTemplateSelector and CustomDataTemplateSelector. So if you will use this approach - you just need to be sure that you will bind to your collection and your collection will have a right order of elements: 10 elements from first ListBox, other elements from second ListBox.

WPF controls, saving real estate

I'm pretty new to WPF and C# and am trying to help out on some GUI stuff for work. We basically have 3 sections, a LHS (left hand side) [section 1], a RHS that has a top and bottom section [section 2 and section 3]. Looks like this
1 | 2
1 | -
1 | 3
They want a way to shrink each section with a button click. Currently the | and - are spacer items and can be dragged (Edit: this is done using a gridsplitter which they don't like). I did a little research and saw there are expander items and accordion items. I didn't know if either could be used for this scenario, and what would be the least hassle. In trying each just a bit, some additional questions for the controls come to mind since I'm not familiar with them.
Expander:
By shrinking section 1, would it make section 2 and 3 then take up the whole screen? Or can this only be done with an Accordion?
Is it hard/easy to change the <> icons to +- icons? If so, any tutorial out there?
Accordion:
Can the <> be changed to +-? If so, any tutorial out there?
Can the default color of blue be changed?
TIA
An Expander sounds like a suitable option for your situation. Fortunately it's included with WPF out of the box, unlike the Accordion control. But I found this question related to the Accordion control and thought it'd be useful for you to check out.
To change the appearance of the Expander toggle button you'll want to modify its control template. Changing the template to display plus or minus instead of arrows isn't too tough. If you visit the link you'll see you're going to want to change ExpanderToggleButton portion of the template.
Since you just want to change from using the arrows to using plus/minus signs you can simply change the Path data for collasped/expanded arrow. You can look here for more infortmation on drawing simple shapes with path.
Here is an example of someone modifying the control template of the Expander. It's for a different tweek in appearance, but it should be useful should you decide to go this route.
EDIT:
Really simple example (without the change in ToggleButton appearance) to get an idea of how to collaspe and save real estate:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColunmDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Expander Name="Section1" Grid.RowSpan="2" Grid.Colunm="0" ExpandDirection="Left">
<!-- Stuff goes here -->
</Expander>
<Expander Name="Section2" Grid.RowSpan="0" Grid.Colunm="1"
<!-- Stuff goes here -->
</Expander>
<Expander Name="Section3" Grid.RowSpan="1" Grid.Colunm="0"
<!-- Stuff goes here -->
</Expander>
</Grid>
You could use GridSplitter. The user can drag them to change the size. Not a click - a drag.
<GridSplitter Grid.Row="1" Grid.Column="1"
Width="3" Background="Purple" VerticalAlignment="Stretch" HorizontalAlignment="Center" ShowsPreview="False" >

Categories

Resources