I'd like to arrange some TextBlocks horizontally without any margins. I can see that my TextBlock is as small as it should be, but for some reason a lot of space is added around it. I think it has something to do with the ListView or its styling, but I don't know what.
I have a following layout:
<ListView Width="Auto" SelectionMode="None" Background="#654321" ItemsSource="{Binding}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Border Background="Black">
<TextBlock Text="{Binding}" Margin="0,0,0,0"/>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
<x:String>A</x:String>
<x:String>B</x:String>
<x:String>C</x:String>
<x:String>D</x:String>
<x:String>E</x:String>
</ListView>
What you need to change is the ItemContainerStyle. You can get the Style from here.
The big thing to notice is that the default Margin of the Style is:
<Setter Property="Margin" Value="0,0,18,2"/>
Which explains the large gap. Change it to:
<Setter Property="Margin" Value="0,0,0,2"/>
And that should help solve your issue.
One last thing to note is that they also have a default ContentMargin="4" (if using the ListViewItemsPresenter) or a bunch of Margins of 4 spread throughout the style (especially on the Borders), which you may need to change as well.
The other way to look at it - ListView is really designed as a control where you can tap, select, drag and otherwise interact with the items. I think if you want to remove all the features that ensure the sizes are touchable with fat fingers - you might just be better off using something like the base ItemsControl or ListBox which might not have these limitations. If you get rid of all the margins and leave your items so small - there's no point in using the ListView and it will just complicate things and make performance bad.
Related
I have to create a control which meets the following requirements:
Items are displayed in cells of a "table"
Items are selectable
Items are drag n droppable
I have 2 approaches:
Using an ItemsControl with a Grid as it's ItemsPanelTemplate
Big problem: ItemsControl doesnt support selection out of the box
Use a DataGrid (seems obscure to me, since it's "not designed for this")
Here's the ItemsControl I am speaking of:
<ItemsControl Grid.Column="1" Grid.Row="2" Margin="5,5,5,0" BorderThickness="1" BorderBrush="Gray" Name="ItemsRack">
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding RowPos}" />
<Setter Property="Grid.Column" Value="{Binding ColPos}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Items are displayed in cells of a "table"
You have a couple options:
Use DataGrid: It does have "cells" and provides some features for editing them. If you get to know it well, you can do even more complex stuff.
Create your own? This ensures you are in control of everything and know how everything works. If this is a big project, I'd go with this option. Study the DataGrid and emulate it. If you run into roadblocks, check out third-party solutions and try to learn from them.
Go third-party: Xceed has a free DataGrid that provides more features than the standard .NET one probably ever will. Cells are definitely present and the features are seemingly enough.
http://wpftoolkit.codeplex.com/
Items are selectable
ListBox/ListView is a reasonable alternative, but probably not what you're looking for.
ItemsControl is limited in what it can do and does NOT support item selection.
DataGrid: Your best bet. Refer to first response.
Items are drag n droppable
Look into GongSolutions' drag/drop library. The rumors really are true, it works wonders.
https://github.com/punker76/gong-wpf-dragdrop
Keep in mind, if you decide to roll out your own DataGrid, it is no simple task. Fun, but difficult.
Scenario:
I am working on a Store App in WinRT/Win8.
I have a ScrollView, with a custom UserControl child inside - all as part of one "main" UserControl.
When the main UserControl (with the ScrollView -> child UserControl) in is Initialized/navigated to - even with the App width not full-screen; the UserControl is at the full width of the ScrollView - as desired. Images below:
Image 1 - main User Control Opens with Window Fullscreen
Image 2 - main User Control Opens Starts Half-Width (or any width)
The ScrollView itself is within a Grid and keeps with the full width of the App window, even when it's resized - as desired.
Issue:
The issue I'm having is that when I resize the App window horizontally, the child UserControl does not keep the same width as its parent ScrollView's.
This causes the ScrollView to then have Horizontal Scrollbars - which I do not want.
Image 3 - Window Horizontal Width Resized
I want to keep the width of the child to be bound inside the width of the ScrollView with no Horizontal Scrollbars (as in Image 2).
Markup is similar to this (I have stripped down for readability):
<Grid>
<!-- Some row/column definitions in here -->
...
<!-- A header TextBlock -->
...
<ScrollViewer x:Name="scrlTableRows" Grid.ColumnSpan="3" Grid.Row="1"
HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
Padding="66,0,66,40" ZoomMode="Disabled">
<local:MyCustomUserControl Margin="0,10,0,10" HorizontalAlignment="Stretch" />
</ScrollViewer>
...
<!-- Just a button here-->
</Grid>
I have already tried setting (on the child custom UserControl):
Width="{Binding Path=ActualWidth, ElementName=scrlTableRows}"
The child is not set at the full width of the ScrollView to start with (which is what I need), and doesn't resize the width with its parent either - giving me scrollbars
Width="{Binding Path=Width, ElementName=scrlTableRows}" The child does start at the full width of the parent, but doesn't resize - giving me scrollbars
I have also tried placing the UserControl inside a Grid (within the ScrollView), amongst many other HorizontalAligment and Width properties.
All to no avail.
No other similar situations/answers have worked from other helpful fellows at StackOverflow.
Obviously, I need the vertical scrollbars - as is kind of evident; before anyone asks.
Can anybody give me any pointers, please?
Update:
Here is the custom UserControl's Xaml, as requested by #LovetoCode:
<UserControl *usual user control declaritive stuff in here*>
<UserControl.Resources>
<CollectionViewSource x:Key="FieldViewModelsSource" Source="{Binding ItemToEdit.FieldViewModels}"/>
<datatemplateselectors:FieldViewModelDataTemplateSelector
x:Key="FieldViewModelDataTemplateSelector"
AudioFieldTemplate="{StaticResource TableRowAudioFieldDataTemplate}"
CheckboxFieldTemplate="{StaticResource TableRowCheckboxFieldDataTemplate}"
DatasetFieldTemplate="{StaticResource TableRowDatasetFieldDataTemplate}"
DateFieldTemplate="{StaticResource TableRowDateFieldDataTemplate}"
DateTimeFieldTemplate="{StaticResource TableRowDateTimeFieldDataTemplate}"
DropdownFieldTemplate="{StaticResource TableRowDropdownFieldDataTemplate}"
FileFieldTemplate="{StaticResource TableRowFileFieldDataTemplate}"
GpsFieldTemplate="{StaticResource TableRowGpsFieldDataTemplate}"
GridFieldTemplate="{StaticResource TableRowGridFieldDataTemplate}"
ImageFieldTemplate="{StaticResource TableRowImageFieldDataTemplate}"
LabelFieldTemplate="{StaticResource TableRowLabelFieldDataTemplate}"
MultichoiceCheckboxFieldTemplate="{StaticResource TableRowMultichoiceCheckboxFieldDataTemplate}"
RadioFieldTemplate="{StaticResource TableRowRadioFieldDataTemplate}"
RangeSliderFieldTemplate="{StaticResource TableRowRangeSliderFieldDataTemplate}"
SignatureFieldTemplate="{StaticResource TableRowSignatureFieldDataTemplate}"
SplitterFieldTemplate="{StaticResource TableRowSplitterFieldDataTemplate}"
TextFieldTemplate="{StaticResource TableRowTextFieldDataTemplate}"
TextareaFieldTemplate="{StaticResource TableRowTextareaFieldDataTemplate}"
TimeFieldTemplate="{StaticResource TableRowTimeFieldDataTemplate}"
VideoFieldTemplate="{StaticResource TableRowVideoFieldDataTemplate}"/>
</UserControl.Resources>
<Grid>
<ItemsControl ItemsSource="{Binding Source={StaticResource FieldViewModelsSource}}"
ItemTemplateSelector="{StaticResource FieldViewModelDataTemplateSelector}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Margin="10,0,10,0" Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</UserControl>
Note that the DataTemplate resources in the UserControl resources are custom UserControls that are loaded in based on objects in the ViewModel (like in my original image 1).
So, with great thanks to #LovetoCode, I managed to remedy my issue. Still trying to get over my 2-day headache and bruises from banging my head against the desk, though.
I ditched the ScrollViewer and just used my custom UserControl:
<local:TableRowUserControl Grid.Row="1" Grid.ColumnSpan="2"
Margin="66,0,66,40" HorizontalContentAlignment="Stretch" />
Then, as #LovetoCode suggested - I used a ListView instead of ItemsControl. My most sincere apologies. I didn't want to use one first time round because...
Main issue was with the ListView's default style to have hover and tap effects; which I didn't need. I tried to steer clear of disabling the hover/tap from previous experience of failing - miserably.
After a bit of Googling (other search engines are available), I found a simple solution to do this quite easily.
I managed to do it like this:
<ListView x:Name="lstFieldViewModels" ItemsSource="{Binding Source={StaticResource FieldViewModelsSource}}" SelectionMode="None"
ItemTemplateSelector="{StaticResource FieldViewModelDataTemplateSelector}" IsSwipeEnabled="False">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Margin="10,0,10,0" Orientation="Vertical" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
Again, props to #LovetoCode. Gold star and programmer points for you :)
I am experiencing some behaviour in a UWP project that I am unable to understand, however my implementations of this in WPF work as expected.
If I have a StackPanel, and insert some grids, the grids stretch to fill the width of the StackPanel as expected.
<StackPanel Grid.Row="1">
<Grid Background="Blue">
<TextBlock>Item 1</TextBlock>
</Grid>
<Grid Background="Green">
<TextBlock>Item 2</TextBlock>
</Grid>
<Grid Background="Red">
<TextBlock>Item 3</TextBlock>
</Grid>
<Grid Background="Pink">
<TextBlock>Item 4</TextBlock>
</Grid>
</StackPanel>
However, once I try to introduce binding and collections, this behaviour stops happening.
<ItemsControl ItemsSource="{Binding Devices}" Grid.Row="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Background="Violet">
<TextBlock>Hello</TextBlock>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have found similar issues reported dating back to 2010, but none of the solutions have worked thus far. I have also found issues reported here for UWP Grid generally, used in other contexts. I have tried using a ListBox (which behaves the same in this regard), setting HorizontalContentAlignment, using styles as Silverlight users seem to have found joy in doing so, and changing how I express my ItemsControl. Nothing has worked thus far, and I am feeling that there is something wrong with XAML in UWP as I don't seem to experience any issues at all in WPF. Is there a known problem, or am I simply going about this the wrong way?
I simply want the child grid to stretch to fill horizontally. I should mention:
It does behave if I wrap the grid in a ViewBox, but this is not desirable as it has other adverse effects.
If I click on everything down the hierarchy in XAML, starting at ItemsControl, the box rendered around this selection is full width all the way down to (excluding) DataTemplate. DataTemplate and Grid show a tight-bound box, but if I look in the property inspector the Grid has its horizontal alignment as stretch. This leads me to believe that the DataTemplate is wrapping the grid with something that doesn't have a HorizontalAlignment="Stretch", and I have no known mechanism to change this.
This behaviour seems to only appear in the designer of Visual Studio and Expression Blend. Once built and executing on both Phone and Desktop, everything appears to render correctly.
I've generally had very good experiences with the designer, and did not expect this to be the case. Had I just ignored the designer and progressed, I would have realised this sooner. I have reported this issue via the VisualStudio feedback tool.
I have a view where I display a bunch of trading cards. Each card is a user control, and these are all displayed in a window. There are 4 cards to a row for however many rows are in some observable collection of cards. I want to be able to print this. I have done this in the past by recreating all the UI elements in the code-behind, but I want to rewrite this using MVVM, and even though I could still do this method in MVVM, it doesn't seem to be the cleanest solution. Does anyone know a simpler way to achieve this? Here is my XAML code for the Window of what I want to print:
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding StateManager.Cards}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type cardModels:AttackCard}">
<StackPanel>
<cardViews:AttackCardControl />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type cardModels:EquipmentCard}">
<StackPanel>
<cardViews:EquipmentCardControl />
</StackPanel>
</DataTemplate>
...
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="960"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
As you can see, I have an ItemsControl that contains all the cards within a wrap panel with a fixed Width. The width of each Card is exactly 240, so this allows exactly 4 cards to fit per row. The Data Templates are for the displaying the different types of cards that all inherit from a Card class and are in an ObservableCollection. Any one have any ideas on how to print this? From my past program, I have also learned that only 2 rows will fit on a sheet of paper and it must be printed at a 90 degree angle (landscape view). Thank you for any help!
<WrapPanel
HorizontalAlignment="Center"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<GroupBox
Header="{DynamicResource ResourceKey=StampUserTab_Strings}"
BorderThickness="1.3"
Style="{StaticResource GroupBoxBorder}" >
<ListBox
Grid.Row="1"
Name="ComponentBox"
ItemTemplate="{DynamicResource StringTemplate}"
VerticalContentAlignment="Stretch"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"
VerticalAlignment="Stretch"
ItemsSource="{Binding ActiveSettings.Components}"
SelectionChanged="ComponentBox_SelectionChanged"
Style="{StaticResource ResourceKey=SettingsListBoxUser}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</GroupBox>
</WrapPanel>
This is my code. The main problem is, that when i add items to the listbox, it keeps expanding out of my screen. I want to make it bound to screen, so when it reaches the bottom, the vertical scroll appers and can be used to scroll the content.
I've tried to set the Height of the grid ro to *, but it didn't help.
Any ideas?
Edit:
The problem was the WrapPanel. I changed it to Grid, defined rows and columns with * heights and widths. After adding my elements to the grid rows and colums the listbox were collapsed to scrolls after the expanding. Thank you for the help.
It seems as though you could do with reading through the Panels Overview page on MSDN. Different Panels have different behaviours and it's pretty important that all new WPF developers know the differences. For example, a Grid can automatically resize its content (the controls placed inside it), whereas a WrapPanel will not.
Therefore, when wishing to constrain the dimensions of your control(s), you should put them into a Grid, or one of the other Panels that provide that functionality and avoid the ones that don't.
You said:
I've tried to set the Height of the grid row to *, but it didn't help
That's because your ListBox is not in a Grid... its parent WrapPanel may be in the Grid, so you could try to set the Grid.Row on that instead.