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!
Related
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.
<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.
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.
I recently got myself into Silverlight and I'm trying to develop an application where it reads data from XML.
My problem is that I have never understood how to actually navigate/make views visible/hidden/collapsed depending on what button the client is clicking. In example, this project reads the menu structure from a XML file and I'm using an ItemsControl to display the menuitems like this:
<ItemsControl ItemsSource="{Binding MenuItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Width="900" Height="40"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Tag="{Binding Url}" Content="{Binding Name}" Click="Button_Click"></Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This code is in my MenuView.xaml (I'm using MVVM by the way) and on my MainPage.xaml I've included the MenuView like this:
<views:MenuView x:Name="menu" />
Now, when a user click one of the buttons, I need to show the correct view on my mainpage. The tricky thing (for me at least) is, that the content from the XML file is "of-type", so basically I have these views:
TextPageView
NewsPageView
Where the NewsPageView's layout is different than the TextPageView, which is just a regular textpage really.
How exactly should I be navigating/hiding/showing these views without using the navigation framework? :-)
Hope my question is clear, if not - please let me know and I will try to elaborate!
Thanks in advance.
All the best,
Bo
The Navigation Framework is your friend :)
Im a beginner in WPF programming, coming from .NET 2.0 C#.
Im trying to make a horizontal StackPanel which should be filled with data from a table in a database. The problem is that I want it to display an image with some text from the table below and then stack those two items horizontally.
Here's some pseudo-code to display what I want to do:
<StackPanel Orientation="horizontal" ItemsSource="{Binding Path=myTable}">
<StackPanel>
<Image Source="User.png"/>
<Label HorizontalAlignment="Center" Content="{Binding Path=UserName}"></Label>
</StackPanel>
</StackPanel>
I simply cannot figure oout how to do this.
Julien's answer is correct for your written description, however, looking at your XAML, it appears you are looking for something like the following:
<DataTemplate x:Key="UserDataTemplate">
<StackPanel>
<Image Source="User.png"/>
<Label HorizontalAlignment="Center" Content="{Binding Path=UserName}" />
</StackPanel>
</DataTemplate>
<ItemsControl x:Name="UserList" ItemTemplate="{StaticResource UserDataTemplate}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
You definately need an ItemsControl (or some derivation of) to bind your source to. Then you can change the the orientation by setting it's items panel (which I believe is a VirtualizingStackPanel with Vertical orientation by default) so just set it to a VirtualizingStackPanel with Horizontal Orientation. Then you can set the ItemsTemplate for each of your items to the layout you desire (an image stacked on top of text bound from your database).
Basically, you want to use a control capable of displaying an enumeration of objects. The control capable of this is the class ItemsControl and all of its descendants (Selector, ListBox, ListView, etc).
Bind the ItemsSource property of this control to a list of objects you want, here a list of users you've fetched from the database. Set the ItemTemplate of the control to a DataTemplate that will be used to display each item in the list.
Sample code:
In a Resources section (for example Window.Resources):
<DataTemplate x:Key="UserDataTemplate">
<StackPanel Orientation="Horizontal">
<Image Source="User.png"/>
<Label HorizontalAlignment="Center" Content="{Binding Path=UserName}" />
</StackPanel>
</DataTemplate>
In your Window/Page/UserControl:
<ItemsControl x:Name="UserList" ItemTemplate="{StaticResource UserDataTemplate}" />
In your code behind:
UserList.ItemsSource = ... // here, an enumeration of your Users, fetched from your db