How to set two alignment in wrappanel - c#

How can I get a wrappanel like the pics below? The two button < > and textblock align to left, and the textbox align to right, when I resize width of windows, the textbox auto wrap to new line.

Here is a quick and dirty way of doing it.
<WrapPanel Orientation="Horizontal" SizeChanged="WrapPanel_SizeChanged">
<TextBlock x:Name="DateTextBlock" TextWrapping="Wrap" MinWidth="280"><Run Text="July 03-09, 2011"/></TextBlock>
<TextBox x:Name="SearchTextBox" Width="250" HorizontalAlignment="Right" />
</WrapPanel>
Then in your your WrapPanel_SizeChanged handler you simply make the DataTextBlock as wide as possible - as wide as the panel less the width of the Search TextBox.
private void WrapPanel_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
{
var panel = (WrapPanel)sender;
var maxWidth = panel.ActualWidth - SearchTextBox.ActualWidth;
DateTextBlock.Width = maxWidth;
}

Related

UWP - How do I center a button?

I created a UWP solution and created a button. There are no problems with the buttons.
I do not know how to center the button in the window.
Code
StackPanel stackPanel1 = new StackPanel();
Button TestButton = new Button();
TestButton.Content = "Test";
stackPanel1.Children.Add(subscribeButton);
Window.Current.Content = stackPanel1;
This line is all you need.
TestButton.HorizontalAlignment = HorizontalAlignment.Center;
Changing the position of the button to half of the form's width and height will work.
Point point = new Point(this.Width / 2 - (button1.Width/2), this.Height / 2 - (button1.Height/ 2));
button1.Location = point;
The added - (button1.Width/2) is because the button's position is based on the upper right hand corner of the button, and not actually the center.
You can set HorizontalAlignment something like these inside the stackpanel...
<StackPanel Margin="10,0,0,0" Orientation="Horizontal" Grid.Column="0">
<TextBlock Grid.Column="1" Grid.Row="0" FontSize="16" HorizontalAlignment="Center">2. Draw a pattern</TextBlock>
<Button x:Name="DeleteSiteButton" Content="Delete Site"
HorizontalAlignment="Right" Margin="0,0,0,0" VerticalAlignment="Top" Click="DeleteSiteButton_Click"/>
<Button x:Name="AddSiteButton" Content="Add Site" HorizontalAlignment="Right"
Margin="10,0,0,0" VerticalAlignment="Top" Click="AddSiteButton_Click"/>
</StackPanel>
StackPanel control arranges child elements into a single line that can be oriented horizontally or vertically. When the Orientation property is set to Vertical(The default value is Vertical), the VerticalAlignment property of the button control will be invalid. Similarly, when the Orientation property is set to Horizontal, the HorizontalAlignment property of the button control will be invalid.
If you add a button control into a StackPanel, the HorizontalAlignment property and VerticalAlignment property of the button control will not work at the same time, that is, the button control can not be centered in a StackPanel.
We suggest that you could add the button control to a Grid panel, like this:
Grid gridPanel1 = new Grid();
Button TestButton = new Button();
TestButton.Content = "Test";
TestButton.HorizontalAlignment = HorizontalAlignment.Center;
TestButton.VerticalAlignment = VerticalAlignment.Center;
gridPanel1.Children.Add(TestButton);
Window.Current.Content = gridPanel1;

UWP Scroll Text from end to start

I am implementing a scrolling text that when pointer enters it, it starts scrolling its content.
I am able to get it scrolling using the code below:
private DispatcherTimer ScrollingTextTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(16) };
ScrollingTextTimer.Tick += (sender, e) =>
{
MainTitleScrollViewer.ChangeView(MainTitleScrollViewer.HorizontalOffset + 3, null, null);
if (MainTitleScrollViewer.HorizontalOffset == MainTitleScrollViewer.ScrollableWidth)
{
MainTitleScrollViewer.ChangeView(0, null, null);
ScrollingTextTimer.Stop();
}
};
XAML:
<ScrollViewer
x:Name="MainTitleScrollViewer"
Grid.Row="0"
Grid.Column="1"
Margin="10,5"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Disabled">
<TextBlock
x:Name="MainTitleTextBlock"
VerticalAlignment="Bottom"
FontSize="24"
Foreground="White" />
</ScrollViewer>
However, there is an additional feature that I want to implement. When the text scrolls to its end, I don't want it to scroll back to the start. I want it to keep scrolling to the start. You can see what I mean from the screenshots I posted below. The screenshots are from Groove Music. You may need to check it out if I didn't explain my question well.
A possible solution might be doubling the text and putting some space between them. But I don't know when to stop scrolling if so.
The effect of this kind of marquee is recommended to use Storyboard. The timer may cause lack due to time interval.
Here is a complete demo, I hope to help you.
xaml
<Grid>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="Gray" BorderThickness="1" Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="ms-appx:///Assets/StoreLogo.png" Width="100" Height="100" VerticalAlignment="Center"/>
<StackPanel Grid.Column="1" Margin="20,0,0,0" VerticalAlignment="Center">
<ScrollViewer Width="200"
PointerEntered="ScrollViewer_PointerEntered"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
PointerExited="ScrollViewer_PointerExited">
<TextBlock FontSize="25" x:Name="TitleBlock">
<TextBlock.RenderTransform>
<TranslateTransform X="0"/>
</TextBlock.RenderTransform>
</TextBlock>
</ScrollViewer>
<TextBlock FontSize="20" FontWeight="Bold" Text="Gotye" Margin="0,10,0,0"/>
</StackPanel>
</Grid>
</Grid>
xaml.cs
Storyboard _scrollAnimation;
public ScrollTextPage()
{
this.InitializeComponent();
string text = "How about you?";
TitleBlock.Text = text + " " + text;
}
private void ScrollViewer_PointerEntered(object sender, PointerRoutedEventArgs e)
{
AnimationInit();
_scrollAnimation.Begin();
}
private void ScrollViewer_PointerExited(object sender, PointerRoutedEventArgs e)
{
_scrollAnimation.Stop();
}
public void AnimationInit()
{
_scrollAnimation = new Storyboard();
var animation = new DoubleAnimation();
animation.Duration = TimeSpan.FromSeconds(5);
animation.RepeatBehavior = new RepeatBehavior(1);
animation.From = 0;
// Here you need to calculate based on the number of spaces and the current FontSize
animation.To = -((TitleBlock.ActualWidth/2)+13);
Storyboard.SetTarget(animation, TitleBlock);
Storyboard.SetTargetProperty(animation, "(UIElement.RenderTransform).(TranslateTransform.X)");
_scrollAnimation.Children.Add(animation);
}
Simply put, scrolling the TextBlock horizontally is more controllable than scrolling the ScrollViewer.
The idea is similar to yours, using a string stitching method to achieve seamless scrolling, and calculate the width of the space by the current font size, so as to accurately scroll to the beginning of the second string.
Best regards.
This is my way of doing it and source code is here(xaml) and here(csharp):
I created a UserControl called ScrollingTextBlock.
This is XAML content of the UserControl.
<Grid>
<ScrollViewer x:Name="TextScrollViewer">
<TextBlock x:Name="NormalTextBlock" />
</ScrollViewer>
<ScrollViewer x:Name="RealScrollViewer">
<TextBlock x:Name="ScrollTextBlock" Visibility="Collapsed" />
</ScrollViewer>
</Grid>
Basically, you need two ScrollViewers that overlaps.
The first ScrollViewer is for detecting if the text is scrollable. And the TextBlock in it is for putting the text.
The second ScrollViewer is the real ScrollViewer. You will be scrolling this one not the first one. And the TextBlock in it will have its Text equal to
ScrollTextBlock.Text = NormalTextBlock.Text + new string(' ', 10) + NormalTextBlock.Text
The new string(' ', 10) is just some blank space to make your text not look concatenated tightly, which you can see from the image in the question. You can change it into whatever you want.
Then in the csharp code you need (explanations are in the comments):
// Using 16ms because 60Hz is already good for human eyes.
private readonly DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(16) };
public ScrollingTextBlock()
{
this.InitializeComponent();
timer.Tick += (sender, e) =>
{
// Calculate the total offset to scroll. It is fixed after your text is set.
// Since we need to scroll to the "start" of the text,
// the offset is equal the length of your text plus the length of the space,
// which is the difference of the ActualWidth of the two TextBlocks.
double offset = ScrollTextBlock.ActualWidth - NormalTextBlock.ActualWidth;
// Scroll it horizontally.
// Notice the Math.Min here. You cannot scroll more than offset.
// " + 2" is just the distance it advances,
// meaning that it also controls the speed of the animation.
RealScrollViewer.ChangeView(Math.Min(RealScrollViewer.HorizontalOffset + 2, offset), null, null);
// If scroll to the offset
if (RealScrollViewer.HorizontalOffset == offset)
{
// Re-display the NormalTextBlock first so that the text won't blink because they overlap.
NormalTextBlock.Visibility = Visibility.Visible;
// Hide the ScrollTextBlock.
// Hiding it will also set the HorizontalOffset of RealScrollViewer to 0,
// so that RealScrollViewer will be scrolling from the beginning of ScrollTextBlock next time.
ScrollTextBlock.Visibility = Visibility.Collapsed;
// Stop the animation/ticking.
timer.Stop();
}
};
}
public void StartScrolling()
{
// Checking timer.IsEnabled is to avoid restarting the animation when the text is already scrolling.
// IsEnabled is true if timer has started, false if timer is stopped.
// Checking TextScrollViewer.ScrollableWidth is for making sure the text is scrollable.
if (timer.IsEnabled || TextScrollViewer.ScrollableWidth == 0) return;
// Display this first so that user won't feel NormalTextBlock will be hidden.
ScrollTextBlock.Visibility = Visibility.Visible;
// Hide the NormalTextBlock so that it won't overlap with ScrollTextBlock when scrolling.
NormalTextBlock.Visibility = Visibility.Collapsed;
// Start the animation/ticking.
timer.Start();
}

UWP XAML Popup not respecting VerticalAlignment?

I'm trying to center a Popup in a Windows Store/UWP app.
In brief, I'm taking MainPage and adding...
A TextBlock with some text
A Button with an event handler, Button_Click
A Popup named popupTest. It contains...
A Border with...
A StackPanel with
A TextBlock
A Button. This Button's event handle sets the Popup's IsOpen to false.
Button_Click calls _centerPopup, which tries to center the Popup and then sets IsOpen to true. I can't get this to work.
private void _centerPopup(Popup popup, Border popupBorder, FrameworkElement extraElement = null)
{
double ratio = .9; // How much of the window the popup fills, give or take. (90%)
Panel pnl = (Panel)popup.Parent;
double parentHeight = pnl.ActualHeight;
double parentWidth = pnl.ActualWidth;
// Min 200 for each dimension.
double width = parentWidth * ratio > 200 ? parentWidth * ratio : 200;
double height = parentHeight * ratio > 200 ? parentHeight * ratio : 200;
popup.Width = width;
popup.Height = height;
//popup.HorizontalAlignment = HorizontalAlignment.Center;
popup.VerticalAlignment = VerticalAlignment.Top; // <<< This is ignored?!
// Resize the border too. Not sure how to get this "for free".
popupBorder.Width = width;
popupBorder.Height = height;
// Not using this here, but if there's anything else that needs resizing, do it.
if (null != extraElement)
{
extraElement.Width = width;
extraElement.Height = height;
}
}
If I don't try to resize and center the Popup in Button_Click, here's what I get after clicking "Click Me"...
private void Button_Click(object sender, RoutedEventArgs e)
{
//_centerPopup(this.popupTest, this.popupTestBorder);
this.popupTest.IsOpen = true;
}
If I uncomment out the call to _centerPopup, I get this, with the popup staying under the button:
private void Button_Click(object sender, RoutedEventArgs e)
{
_centerPopup(this.popupTest, this.popupTestBorder);
this.popupTest.IsOpen = true;
}
That's no good. I thought popup.VerticalAlignment = VerticalAlignment.Top; would've fixed that.
FrameworkElement.VerticalAlignment Property
Gets or sets the vertical alignment characteristics applied to this element when it is composed within a parent element such as a panel or items control.
Move Popup to top of StackPanel?
Strangely, if I move the Popup up to the top of my StackPanel, it actually pushes the other controls down after being shown.
Clicking "Click Me" without _centerPopup:
That looks promising! It's floating over the other controls nicely, and there's no obvious impact to the layout after it's closed.
But add back _centerPopup, even after commenting out setting VerticalAlignment to Top, and things die a horrible, fiery death.
It looks perfect until you notice that every other control was pushed down. ??? Here's after clicking "Click to close":
Other controls are pushed down permanently. Why does that happen? Shouldn't the popup float like it did before I resized it?
Full Source
XAML
<Page
x:Class="PopupPlay.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PopupPlay"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel Name="StackMain">
<TextBlock>
This is some text<LineBreak />
This is some text<LineBreak />
This is some text<LineBreak />
This is some text<LineBreak />
</TextBlock>
<Button Click="Button_Click" Content="Click Me"></Button>
<Popup x:Name="popupTest">
<Border
Name="popupTestBorder"
Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
BorderBrush="{StaticResource ApplicationForegroundThemeBrush}"
BorderThickness="2">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Name="txtPopup"
Text="This is some text"
FontSize="24"
HorizontalAlignment="Center" />
<Button Name="btnClose"
Click="btnClose_Click"
Content="Click to close"></Button>
</StackPanel>
</Border>
</Popup>
</StackPanel>
</Page>
Full MainPage.xaml.cs code
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
namespace PopupPlay
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
_centerPopup(this.popupTest, this.popupTestBorder);
this.popupTest.IsOpen = true;
}
private void _centerPopup(Popup popup, Border popupBorder, FrameworkElement extraElement = null)
{
double ratio = .9; // How much of the window the popup fills, give or take. (90%)
Panel pnl = (Panel)popup.Parent;
double parentHeight = pnl.ActualHeight;
double parentWidth = pnl.ActualWidth;
// Min 200 for each dimension.
double width = parentWidth * ratio > 200 ? parentWidth * ratio : 200;
double height = parentHeight * ratio > 200 ? parentHeight * ratio : 200;
popup.Width = width;
popup.Height = height;
//popup.HorizontalAlignment = HorizontalAlignment.Center;
popup.VerticalAlignment = VerticalAlignment.Top; // <<< This is ignored?!
// Resize the border too. Not sure how to get this "for free".
popupBorder.Width = width;
popupBorder.Height = height;
// Not using this here, but if there's anything else that needs resizing, do it.
if (null != extraElement)
{
extraElement.Width = width;
extraElement.Height = height;
}
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
this.popupTest.IsOpen = false;
}
}
}
There are several questions that seem related. I do not see a viable fix. (Note: These are not all UWP specific.)
Center Popup in XAML
Place Popup at top right corner of a window in XAML
How to set vertical offset for popup having variable height
Painfully, this same setup is working for me in another app when it's positioned in a much more complicated grid with a Pivot, but I see that pivots are buggy.
Wpf's Placement stuff sounds promising, but doesn't exist in UWP-land.
Your Popup is inside a vertical StackPanel, which means the StackPanel will lay out the popup alongside the other child elements of the panel, which is why it pushes down the text.
Also, the VerticalAlignment is being ignored by the panel because the panel allocated exactly enough vertical space for the popup's size, and so there is no room for it to align the popup vertically within the space it was allocated.
I would suggest using a Grid as the root element for the Page, and putting the StackPanel and Popup directly inside the Grid, like this:
<Grid>
<StackPanel Name="StackMain">
<TextBlock>
This is some text<LineBreak />
This is some text<LineBreak />
This is some text<LineBreak />
This is some text<LineBreak />
</TextBlock>
<Button Click="Button_Click" Content="Click Me"></Button>
</StackPanel>
<Popup x:Name="popupTest">
<Border
Name="popupTestBorder"
Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
BorderBrush="{StaticResource ApplicationForegroundThemeBrush}"
BorderThickness="2">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Name="txtPopup"
Text="This is some text"
FontSize="24"
HorizontalAlignment="Center" />
<Button Name="btnClose"
Click="btnClose_Click"
Content="Click to close"></Button>
</StackPanel>
</Border>
</Popup>
</Grid>
Grids are good for this purpose, when you want to have overlapping elements or multiple elements that do not affect the position and size of any other child element. You want the layout of the popup to be separate from the layout of the stack panel and its children, so you should organize your XAML as such.
Try changing your xaml as follows...
<Page...>
<Grid x:Name="LayoutRoot">
<Popup>
</Popup>
<Grid x:Name="ContentPanel">
</Grid>
</Grid>
</Page>
So move the Popup control outside the content area and put your stacklayout with all content inside the ContentPanel Grid ( as shown in code sample above )
That should stop pushing the other controls down...

Windows RT XAML Controls - GridWrap Column autosizing to window size

I have been looking for a resizeable Universal Windows App (RT, UWP) control for handling different screen sizes and scalable controls. What I am looking for is something like a wrapgrid (What I am using below), except that it changes the column width to fill the space when it is resized, like what occurs with the Tubecast app for windows, when you resize the window the columns will expand, or when shrinking, merge once they hit a minimum value.
Currently I am using a wrapgrid control to fill the TV shows into the library, adding a new frame in code, navigating it to a new instance of the LibraryModel Page, passing a class via the onNavigatedTo() method. This XAML page has a min properties of 135x200, and a max properties of 270x400, using static item height and with of 270x400 and visual state groups to change to 125x200 when the width goes below 720px. I tried using a variablesizedwrapgrid, but it wasn't any more helpful.
Is there a control like this that exists for UWP apps? Or will it need to be created manually using C#, or added to the platform later? This control is likely essential for future Windows 10 App development.
Example Screenshot
I suggest you look at view-boxes, might provide a solution.
I figured out a way to make the controls scale to screen sizes, so that they will take up all available real estate, and works well on all devices.
Others shown at bottom of page..
<Grid Background="#FF1D1D1D" x:Name="maingrid" SizeChanged="maingrid_SizeChanged">
<Grid Grid.ColumnSpan="2" Grid.RowSpan="2">
<ScrollViewer x:Name="LibraryScroll">
<Grid>
<Viewbox x:Name="LibraryItemViewbox" Stretch="Uniform" VerticalAlignment="Top" HorizontalAlignment="Left">
<Grid x:Name="Area" Width="{x:Bind maingrid.Width}" Height="{x:Bind maingrid.Height}">
<ItemsControl x:Name="showsPanel" Loaded="showsPanel_Loaded" ItemsSource="{x:Bind Library.LibraryItems, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid x:Name="shows" Orientation="Horizontal" ItemHeight="400" ItemWidth="270" MaximumRowsOrColumns="3"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="viewmodel:LibraryItemModel">
<Button Padding="0" Foreground="Transparent" BorderThickness="0" Tapped="LibraryItem_Tapped" RightTapped="LibraryItem_RightTapped" Holding="Button_Holding"/>
<Grid x:Name="MainGrid" Background="#00A6A6A6" Width="270" Height="400">
<!-- Content -->
</Grid>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Viewbox>
</Grid>
</ScrollViewer>
</Grid>
</Grid>
This is the XAML structure required to scale the content.
The Viewbox is wrapped into a Grid, so that Vertical and Horizontal Alignment still works inside the ScrollViewer. The inner Grid "Area" has its Height and Width bound to the base Grid 'maingrid', so it maintains the aspect ratio of the page.
The Itemscontrol is defined as a WrapGrid, meaning that Item Width has to be defined, meaning this won't work variable sized controls inside (Although possible with some modification). The ItemTemplate is then defined as well (Requiring the Base Grid 'MainGrid' to be the same dimensions as the WrapGrid's ItemWidth and ItemHeight).
Events that are required are SizeChanged on the Base Grid and Loaded on the ItemsControl.
In order to scale the elements when the page is loaded, and scale them when the page is resized, the code looks like this:
private void showsPanel_Loaded(object sender, RoutedEventArgs e)
{
Area.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Resize();
fillGaps(showsPanel.ItemsPanelRoot as WrapGrid);
}
private void Resize()
{
var width = this.ActualWidth;
var height = this.ActualHeight;
var grid = (WrapGrid)showsPanel.ItemsPanelRoot;
int numofColsOrig = grid.MaximumRowsOrColumns;
if (width >= 2800) grid.MaximumRowsOrColumns = 8;
if (width < 2800) grid.MaximumRowsOrColumns = 8;
if (width < 2400) grid.MaximumRowsOrColumns = 7;
if (width < 2000) grid.MaximumRowsOrColumns = 6;
if (width < 1600) grid.MaximumRowsOrColumns = 5;
if (width < 1200) grid.MaximumRowsOrColumns = 4;
if (width < 800) grid.MaximumRowsOrColumns = 3;
if (width < 400)
{
grid.MaximumRowsOrColumns = 2;
if (Library.LibraryItems.Count >= 2) Area.Padding = new Thickness(0);
}
if (numofColsOrig != grid.MaximumRowsOrColumns)
{
fillGaps(grid);
}
}
private void fillGaps(WrapGrid grid)
{
var libraryitems = Library.LibraryItems;
if (libraryitems.Count < grid.MaximumRowsOrColumns && libraryitems.Count != 0)
{
int numOfItemsToFill = grid.MaximumRowsOrColumns - libraryitems.Count;
Area.Padding = new Thickness { Right = (grid.ItemWidth * numOfItemsToFill) };
}
}
private void maingrid_SizeChanged(object sender, SizeChangedEventArgs e) { Resize(); }
The values of widths to change the number of rows will need to be manually tweaked in order to look better with different size objects, and when adding or removing from the ItemSource, Resize(); will have to be called to recalculate the dimensions of the elements, for it to look correct.
You will, of course, need to replace libraryitems with you own ObservableCollection, so that it can get the count of how many objects are in your list, or get the count from your WrapGrid's items count.

Presenting list of steps

I am working on Windows 8 application in C#/XAML.
I have a list of steps to show and the list can have one to many steps.
I have tried the GridView and ListView controls, but with those, it is not possible to have each element have its own height (because one step might have only one line of text, and the next one 3 lines, for example). The VariableSizedGridview does not help either.
What I am trying to achieve is something like the way cooking steps are shown in the Microsoft Bing Food & Drink app. So, steps are shown in rows in the first column, and when the end of the page is reached, it creates a second column, and so on. Like so :
Could anyone please help me find a way to achieve this?
What control to use and how?
It looks very simple, but I was not able to find any solution while searching online.
Thank you
Here is what I have done with the Gridview control (the Listview was quite similar) :
<Grid Name="gridSteps" Grid.Column="3" Margin="25,69,25,69">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="ÉTAPES" FontSize="22" FontWeight="Bold"></TextBlock>
<GridView Grid.Row="1" Name="gvGroupSteps" SelectionMode="None" IsHitTestVisible="False" VerticalAlignment="Top">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel Width="400">
<TextBlock Text="{Binding Order}" Margin="0,15,0,0" FontSize="20" Foreground="Bisque"></TextBlock>
<TextBlock Text="{Binding Description}" Margin="0,5,0,0" FontSize="18" TextWrapping="Wrap"></TextBlock>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel Background="#FFC9C9C9">
<TextBlock Text="{Binding GroupName}" FontSize="20" FontWeight="SemiBold"></TextBlock>
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
</Grid>
You may want to post the XAML that you have tried. It sounds like to me that you need to nest your view items. Consider this very simple example:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ListView>
<ListViewItem>Step 1</ListViewItem>
<ListViewItem>
<ListView>
<ListViewItem>Step 1a</ListViewItem>
<ListViewItem>Step 1b</ListViewItem>
<ListViewItem>Step 1c</ListViewItem>
</ListView>
</ListViewItem>
<ListViewItem>Step 2</ListViewItem>
</ListView>
</Grid>
I have tried the GridView and ListView controls, but with those, it is not possible to have each element have its own height
My recollection is that you can in fact have elements with different heights using those controls. These are both types of ItemsControl, which supports data templating, which in turn allows you to customize the appearance of each item, including its height.
That said, you may find that the simpler ListBox suits your needs in this case. It's hard to say without a code example or other details.
You should read MSDN's Data Templating Overview, which has a thorough discussion of the whole process, along with some good examples of what you can do. Pay particular attention to the section named "Choosing a DataTemplate Based on Properties of the Data Object". While a single template could still have variable height, clearly by using a different template according to your specific needs you can customize each item's style to your heart's content.
If this does not address your question, please provide a more detailed question. You should include a good, minimal, complete code example that shows clearly what you've tried, explaining precisely what that code does and how that's different from what you want it to do.
I have been looking all over the internet for a solution, but could not manage to find anything.
So i decided to do everything myself in C# code.
In short, in have a StackPanel with Orientation set to Horizontal, and I add a Grid to it and add rows to that Grid for every item i have. When the maximum height is reached (based on the screen Height), I add a new Grid to the StackPanel, and so on.
Here is my code if anyone needs it :
// Nombre de lignes maximal (16 lignes à 1080p)
int maxCharCount = (int)Window.Current.Bounds.Height * 16 / 1080;
spIngredients.Children.Clear();
foreach (var groupIngredient in db.Table<GroupIngredient>().Where(x => x.RecipeId == _currentRecipe.Id))
{
int linesCount = 0;
int row = 0;
var gGroup = new Grid();
spIngredients.Children.Add(gGroup);
gGroup.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
var groupName = new TextBlock() { Text = groupIngredient.Name, FontSize = 20, FontWeight = FontWeights.SemiBold, Margin = new Thickness(10) };
gGroup.Children.Add(groupName);
Grid.SetRow(groupName, row);
foreach (var ingredient in db.Table<Ingredient>().Where(x => x.GroupIngredientId == groupIngredient.Id))
{
// Nombre de lignes, split à 45 char
linesCount += 1 + ingredient.IngredientFull.Length / 45;
if (linesCount >= maxCharCount)
{
var gCol = new Grid();
spIngredients.Children.Add(gCol);
gCol.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
var col = new TextBlock() { Text = "", FontSize = 20, FontWeight = FontWeights.SemiBold, Margin = new Thickness(10) };
gCol.Children.Add(col);
gGroup = gCol;
row = 0;
linesCount = 0;
Grid.SetRow(col, row);
}
row++;
ingredient.Quantity = ingredient.Quantity * multiplier;
gGroup.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
var ingredientName = new TextBlock() { Text = ingredient.IngredientFull, Margin = new Thickness(10), FontSize = 18, TextWrapping = TextWrapping.Wrap, MaxWidth = 300 };
gGroup.Children.Add(ingredientName);
Grid.SetRow(ingredientName, row);
}
}

Categories