I am writing a Windows Phone 8 app, and I am having some problems with the UI. I want a control that will stretch to the width of the whole screen, and will flow its children controls horizontally (to fill the space).
Currently, I have a a StackPanel with Orientation = Horizontal, but it doesn't allow the children control (a slider) to have a HorizontalAlignment=Stretch (that actually stretches). I can manually strech the slider, but I don't want to have hardcoded sizes..
Here is the code:
<StackPanel Orientation="Horizontal">
<TextBlock Text="Hue Bins" />
<Slider x:Name="HueBins" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Value="24" Maximum="36" Minimum="1"/>
</StackPanel>
and the resulting image:
In normal WPF, there is the Dockpanel control, but that doesn't seem to exist for WP8. Is there anyway to emulate that behavior?
You can use Grid with two columns:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Hue Bins" />
<Slider x:Name="HueBins" Grid.Column="1" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Value="24" Maximum="36" Minimum="1"/>
</Grid>
You could try the version extracted from Silverlight Toolkit here, with some adjustments they did for WP7
http://www.geekchamp.com/articles/using-dockpanel-in-wp7
or use the whole Silverlight Toolkit if you need more stuff from it
http://silverlight.codeplex.com/
(since Windows Phone Toolkit that was derived from it doesn't seem to contain DockPanel)
some info (but broken download link) on what is needed to compile DockPanel are at http://matthiasshapiro.com/2010/06/28/using-wrappanel-and-dockpanel-in-windows-phone-7-with-blend/
Update: I used the info I mentioned above to set up http://DockPanel.codeplex.com. It works fine, apart from the case where all the top/left/right/bottom/middle items are all added together in the layout, at least on Windows Phone it does some wrong layout in that case
Related
I have a Grid which consists of a ScrollViewer and a ScrollBar which are separated (i.e. the ScrollBar is not bound to the ScrollViewer)
I want both to be synchronized, for instance if the ScrollViewer's VerticalOffset property changes, I want the value of the ScrollBar to change, and vice-versa. I really insist that both should be separated (because in my real project the ScrollViewer is located on a different View)
<Grid Height="200" Width="400">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="6*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Column="0" Background="Gray" />
<ScrollBar Grid.Column="1" Width="30" />
</Grid>
I don't see that you can do this merely by binding a couple of properties.
I think the way to do this is to create two completely separate ScrollViewers and link them together. The one on the left has its scroll bar visibility properties set to hide its scroll bars so all you see is the view. The one on the right just shows the ScrollBar part. (It's possible this might require you defining a custom control template to achieve that effect but it can be done).
Then link them together in code-behind. Use the ScrollChanged event. For example
https://learn.microsoft.com/en-us/answers/questions/43474/wpf-how-to-make-two-panels-share-the-same-vertical.html
For reference, this is a chat application. This should give you some idea of a final goal.
Additionally, I am very new to WPF. This is one of my first applications and I am making this as a proof of concept. I've been using Windows Forms up until this point, so any comparison or reference to it would help me understand a bit better.
So, the issue at hand:
The chat box for my chat application is a StackPanel (should it be?) which is programmatically populated with TextBlock elements. I need to find a way to scroll down this StackPanel once the available space runs out. I also need it to automatically scroll to the bottom (like a chat would; you wouldn't be able to see the most recent message otherwise).
The question: How can I make a ScrollViewer properly size dynamically with a StackPanel?
Additionally, I also need this StackPanel to size dynamically as the window is sized. This, in turn, would affect the scroll bar.
My current "solution" is to use a ScrollViewer with the StackPanel nested. However, the ScrollViewer and StackPanel do not size properly with a change in window size, as shown in screenshot #2. The XAML code and a screenshot of the designer is shown below.
<Window x:Name="Main" x:Class="dprCxUiDemoWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:dprCxUiDemoWpf"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid Background="#FF171717">
<TextBox x:Name="ChatBox" TextWrapping="Wrap" Background="#FF4F4F4F" Foreground="White" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" RenderTransformOrigin="-0.118,12.093" Margin="146,0,0,1" VerticalAlignment="Bottom" Height="46" BorderBrush="#FFFF00F3" KeyDown="ChatBox_KeyDown"/>
<Image x:Name="DprLogo" Source="/dprCxUiDemoWpf;component/Images/logo1.png" HorizontalAlignment="Left" Height="60" Margin="10,0,0,10" VerticalAlignment="Bottom" Width="123"/>
<ScrollViewer Background="Red" Height="Auto" Width="Auto" ScrollViewer.CanContentScroll="True" Margin="146,0,0,0" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Top" MinHeight="372">
<StackPanel x:Name="ChatPanel" Height="Auto" Width="Auto" Background="DimGray" ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</Grid>
</Window>
(source: gcurtiss.dev)
Please note the following regarding the first screenshot:
A. The black column (containing the logo) is simply the background color of the window; there is nothing there.
B. The gray portion is ChatBox (the StackPanel)
C. The pink highlighted box below is the text box where messages are entered.
I appreciate and accept any and all help!
You have to use the Grid panel properly. You layout its children by defining rows and columns. Grid is a column/row based layout container. Then configure row and column definitions to control the resize behavior of the cells and their content.
Using absolute positioning and sizes will of course prevent controls from responding to their parent's size changes. Most control stretch to fit the available space. But this requires dimension properties being set to Auto.
You said you are "more of a hands-on learner", but you should still read some documentations. Otherwise you will significantly slow down your progress until stagnation.
There are tons of blogs waiting for you to read them. To poke around in the dark will get you nowhere. You need at least to know the basics. Instead of waiting 13+ hours for a copy & paste ready answer, you could have finished multiple tutorials already and solve this on your own. Success is a good feeling. This is a very trivial problem.
Find yourself a good tutorial that you find easy to understand and start to experiment with the Grid after reading it.
According to your posted code, you obviously have zero idea how this panel works and how you can use it to align your controls.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollViewer Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
<StackPanel />
</ScrollViewer>
<Image Grid.Row="1" Grid.Column="0"
Height="60"
Width="123 />
<TextBox Grid.Row="1" Grid.Column="1" />
</Grid>
I need to find a way to scroll down this StackPanel once the available space runs out. I also need it to automatically scroll to the bottom (like a chat would; you wouldn't be able to see the most recent message otherwise)
You should read about data-binding and MVVM first. Usually you hold an ObservableCollection of items on your VM and bind them to eg a ListBox on your View.
Then you can scroll-down the ListBox, each time a new item got added to your collection:
private void ScrollRecordsListToBottom()
{
if (RecordsList.Items.Count == 0)
return;
var lastItem = RecordsList.Items[RecordsList.Items.Count - 1];
RecordsList.ScrollIntoView(lastItem);
}
I'm trying to use HorizontalAlignment="Left" in the following situation:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Grid HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Background="Gray" Text="Small Text" TextWrapping="Wrap"/>
<TextBlock Grid.Column="1" Background="White" Text="This is a very large amount of text" TextWrapping="Wrap"/>
<TextBlock Grid.Column="2" Background="Gray" Text="Medium amount of text" TextWrapping="Wrap"/>
</Grid>
</Window>
My goal is to be able to resize the window, and have the three TextBlocks resize themselves proportionally. This works, but the grid is putting some blank space to the right of the final column, and as I try to resize towards the final column, the columns start to shrink. I want this shrinking behavior, but I don't want it to start until there is no more white space to the right of the rightmost column.
I can't use a UniformGrid as the text lengths can vary, and no other built-in WPF control that I've seen has the ability to resize all children when the parent size changes. I've looked into creating a custom panel, but that seems to be more trouble than it's worth. I feel like something much more simple can be done here.
Any suggestions or ideas are appreciated.
You'll have to build your own custom panel, and handle the case where the AvailableWidth is less then the panel's children DesiredWidth
Panel layout in WPF (Grid is a Panel) is a 2 step process, in the first pass the Panel iterates over its children and provides them with the panel's AvailableWidth. The children respond to this by computing their DesiredWidth.
In the second pass the Panel arranges the children according to their DesiredWidth. In this second pass you have access to the width that all the children (in your case, TextBlocks) require. If it is less than the panel's available width you can compute a percentage to give each one so that they appear to shrink uniformly.
Here's a resource that shows how you can create your own custom panel
What about this?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
So, I have a Windows Phone 8.1 application (Windows Store style) and I'm trying to make a simple 3 column layout. I'm running into the problem though that the controls I put in the smaller columns of the grid do not respect the width of the column. The control instead will be some (I assume) default size that is way too big, unless I manually specify in pixels how wide I want the control to be. I don't want to specify pixels though, since I want this to easily work on different screen sizes.
My XAML code:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.15*" />
<ColumnDefinition Width="0.70*" />
<ColumnDefinition Width ="0.15*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="A" HorizontalAlignment="Left" Height="Auto" VerticalAlignment="Stretch" FontFamily="Global User Interface" FontSize="40" Width="auto"/>
<TextBlock Grid.Column="1" HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="B" VerticalAlignment="Center" Height="576" Width="Auto" TextAlignment="Center" FontSize="206" />
<Button Grid.Column="2" Content="C" HorizontalAlignment="Right" VerticalAlignment="Bottom" FontFamily="Global User Interface" FontSize="40" Height="640" Width="auto"/>
</Grid>
Screenshot showing the overflowing "C" button going beyond the column line of the grid
Funny enough, taking this EXACT same XAML code and putting it in a Windows Phone 8.1 Silverlight application results in it working as I'd expect with the controls being fit to the grid
edit: Actually, even setting widths in pixels has no effect... uhh wat?
Set MinWidth="0" on each of your buttons.
I want to create an app that has a listbox on the left side (I'll style it to make it look good later).
On the right side, I want to have an area where I can add controls, etc
So the question is what do I need to do to split the Window into two unequal parts
(left side approx 350 pixels wide and height should be the entire window) and the remainder is for my "canvas."
You can use a Grid:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="350" /> <!-- Or Auto -->
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox Grid.Column="0" />
<Canvas Grid.Column="1" />
</Grid>
Or you could use a DockPanel:
<DockPanel>
<ListBox DockPanel.Dock="Left" Width="350" />
<Canvas />
</DockPanel>
The benefit of the Grid is you have finer control over the layout and could allow the end user to dynamically resize the columns using a GridSplitter.
An alternate approach to CodeNaked's solution can be to use DockPanel where Canvas takes all space that is left automatically and you don't have to work out splits.
Of course this has the limitation of docking only to the four edges (with possibility of stacking up at edges) but I tend to prefer DockPanel when I'm making initial UI as they're rather quick and easy to setup compared to Grid setup which can get complex fairly quickly.
<DockPanel LastChildFill="True">
<ListBox DockPanel.Dock="Left" Width="350"/>
<Canvas />
</DockPanel>