C# WPF XAML status bar alignment - c#

Everything is fine when the text is default on startup before, but when I add song name, status is moving to right and status bar are outside area. after
<StatusBar Margin="0,730,0,0" DockPanel.Dock="Bottom" >
<WrapPanel >
<Label x:Name="tytulUtworu" HorizontalAlignment="Left">music: none </Label>
<Label x:Name="lblstatusPolaczenia" Margin="200,0,0,0" HorizontalAlignment="Center">status: disconnected</Label>
<ProgressBar Width="100" Height="15" Value="50" Margin="200,0,0,0" HorizontalAlignment="Right" />
</WrapPanel>
</StatusBar>
How can I repair this?

Instead of using a WrapPanel, try using a Grid. That way you'll have fixed columns that won't affect the other elements if text is added
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label x:Name="tytulUtworu" HorizontalAlignment="Left">music: none </Label>
<Label x:Name="lblstatusPolaczenia" Grid.Column="1" HorizontalAlignment="Center">status: disconnected</Label>
<ProgressBar Width="100" Height="15" Value="50" Grid.Column="2" HorizontalAlignment="Right" />
</Grid>
You can adjust the Width on each ColumnDefinition to get better sized columns for your use

Firstly, ditch the margins.
They are not helping, they just make things less obvious as to how they should be aligned.
From your margin values, I'm guessing that you want the status bar to show the label on the left, another in the center, and the progress bar on the right.
Below shows how to do this with a second dock panel.
Dock panel is ideal here as it is consistent in the way it reports its size to child components.
If you want to place this status panel on another DockPanel, there are a few things which must be done before it will render as you need it to.
Firstly, you main dock panel must have content, otherwise the boundary panels will not render in the right place.
Secondly, if you have set LastChildFill=True, you must add your main content as the last item.
If you set the main content then add your status bar, even though you have docked it to the bottom, it will still try to fill the panel.
I've updated the code snippet after testing it (my first attempt was typed straight into SO, sorry it didn't work).
<StatusBar DockPanel.Dock="Bottom"
Name="statusBar"
Height="50"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<DockPanel LastChildFill="True"
Width="{Binding ActualWidth, ElementName=statusBar, Mode=OneWay}">
<ProgressBar DockPanel.Dock="Right"
Width="100"
Value="50" />
<Label x:Name="tytulUtworu"
DockPanel.Dock="Left"
ContentStringFormat="music: {0}"
Content="none" />
<Label x:Name="lblstatusPolaczenia"
HorizontalContentAlignment="Center"
Content="disconnected"
ContentStringFormat="status: {0}" />
</DockPanel>
</StatusBar>

Related

Making a Scrollviewer fill the available space in a DockPanel

I somewhat of a WPF noob and am using a DockPanel to display the text content of an email in a TextBox in a ScrollViewer. The panel has a button bar and area for the email headers at the top, a button bar at the bottom, a panel at the right and the email itself should fill the remaining space dynamically:
[Banner at top, below which is a button bar and box with email headers. At the bottom is another full width button bar. The space between them is divided into a fixed-width panel at the right and a large text box for the email contents.]
http://rowlandsoftware.com/Screenshots/LongEmail.png
(The DockPanel sits inside a grid that provides the bit at the very top and is used when the email is not visible.)
The problem is that if the email is too short or too narrow, the textbox fails to fill the remaining width. In this screenshot, you can see some of the underlying stuff between the box and the panel:
[Between the text box and the panel is a column that is not filled. Part of what lies under it can be seen.]
http://rowlandsoftware.com/Screenshots/TooNarrow.png
The XAML is:
<DockPanel x:Name="EmailCanvas" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" Visibility="Collapsed" Height="Auto">
<DockPanel x:Name="topButtonBar" DockPanel.Dock="Top" Height="50" Background="White">
<Button x:Name="btnReturn" DockPanel.Dock="Left" Content="Return to List" Click="btnReturn_Click" />
<Image Width="15" Source="Images/transparent.png" />
<Button x:Name="btnTextToggle" Content="Plain text" Click="btnTextToggle_Click" />
<Button x:Name="btnZoomOut" Content="Zoom Out" />
<Button x:Name="btnZoomIn" Content="Zoom In" />
<Image Width="150" DockPanel.Dock="Right" Source="Images/transparent.png" />
<Button x:Name="btnPrint" DockPanel.Dock="Right" Content="Print" Width="100"/>
<Image DockPanel.Dock="Right" Source="Images/transparent.png" />
</DockPanel>
<StackPanel x:Name="EmailHeaders" Orientation="Horizontal" DockPanel.Dock="Top" Width="Auto" Background="Linen">
<StackPanel Orientation="Vertical">
<TextBlock Text="Subject:" FontSize="16" />
<TextBlock Text="Time Sent:" FontSize="16"/>
<TextBlock Text="Other Recipients: " FontSize="16"/>
</StackPanel>
<StackPanel Orientation="Vertical">
<TextBlock x:Name="labSubject" Text="Subject:" FontSize="16" />
<TextBlock x:Name="labDateTime" Text="Sent:" FontSize="16"/>
<TextBlock x:Name="labSpare" Text="Other Recipients:" FontSize="14"/>
</StackPanel>
</StackPanel>
<DockPanel x:Name="bottomButtonBar" DockPanel.Dock="Bottom" Height="80" >
<Image Width="150" DockPanel.Dock="Left" Source="Images/transparent.png" />
<Button x:Name="btnDelete" DockPanel.Dock="Left" Content="Delete" />
<Image Width="150" Source="Images/transparent.png" />
<Button x:Name="btnSave" Content="Save" />
<Image Width="150" Source="Images/transparent.png" />
<Button x:Name="btnReply" Content="Reply" />
<Image Width="150" DockPanel.Dock="Right" Source="Images/transparent.png" />
</DockPanel>
<StackPanel DockPanel.Dock="Right" Orientation="Vertical" Background="White" Width="150">
<Button x:Name="btnAttachments" Content="Attachment"/>
</StackPanel>
<ScrollViewer x:Name="eTextViewer" VerticalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch">
<TextBox x:Name="eText" Background="White" HorizontalAlignment="Stretch" TextWrapping="Wrap" FontFamily="Verdana" FontSize="18" IsReadOnly="True" />
</ScrollViewer>
<!--Image Width="Auto" Height="Auto" DockPanel.Dock="Bottom" Source="Images/white.png" /-->
<WebBrowser x:Name="eHTML" Height="Auto" DockPanel.Dock="Top" Visibility="Collapsed" />
</DockPanel>
The box is extended only to fill the available height, not the width. The documentation for the DockPanel.LastChildFill Property says,
If you set the LastChildFill property to true, which is the default setting, the
last child element of a DockPanel always fills the remaining space, regardless
of any other dock value that you set on the last child element.
msdn.microsoft.com/en-us/library/system.windows.controls.dockpanel.lastchildfill%28v=vs.110%29.aspx
That does not appear to be the case: in my program it is only filling height, not width. LastFillChild=true is the default, but explicitly setting it to True or False doesn't make a blind bit of difference.
Interestingly, if you set DockPanel.Dock="Top" on the ScrollViewer, it fills the available width but not the height, leaving some of the underlying stuff showing between the text box and the bottom button bar. Again this is contrary to the documentation which says that the dock value set on the last child element is ignored.
Setting HorizontalAlignment="Stretch" to both the ScrollViewer and the TextBox and HorizontalContentAlignment="Stretch" to the ScrollViewer makes not a jot of difference.
So my question is, how can I ensure that the textbox fills the available space in the DockPanel even when the contents of the email are too short?
UPDATE: I have just noticed that if I remove the WebBrowser that is set initially to Visibility="Collapsed", then it works fine. I guess that its presence fools the DockPanel into regarding it as the LastChild even though it is Collapsed.
However, I need to toggle between displaying the email in the web browser and the text box, so removing it isn't an option. Both need to be treated as last child when they are visible. Any ideas?
UPDATE 2: So I wrap the scrollviewer and the web browser in another container, e.g. grid, which is the Last Child. Then I can toggle between the the two but they both fill the space.
Thanks guys. I wouldn't have got there without humiliating myself in public ;)
DockPanel will work, but beware of Collapsed items. Although the documentation says that a collapsed item has no effect on layout, with DockPanel it does if it is the LastChild.
The solution in my case was to add another container as the last child, and place the two items that I wanted to toggle between in that container. Then both will fill the remaining space in the panel.

Controls within grid column don't respect size of column

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.

Force Size on a Viewbox's Children

So I have a rather interesting question. I have a viewbox that has a few elements in it (a custom user control for an image, a canvas, a label, and a textbox). What I want is to try and have all elements scale with the viewbox, but I want the label and the textbox to have a "Max Size." I have tried using a max width and height on these controls but they seem to ignore it. If someone could take a look at my code below an slap me for what I am doing wrong that would be appreciated.
<Viewbox Name="myViewBox" Stretch="Uniform">
<!--Grid used to track mouse movements in this element for other reasons -->
<Grid Name="grdViewboxGrid" MouseMove="trackMouse">
<Canvas Name="cvsViewboxCanvas" MinWidth="270" MinHeight="270"
VerticalAlignment="Top" HorizontalAlignment="Center"
Panel.ZIndex="1" Background="Black"
MouseUp="Canvas_MouseUp"
MouseMove="Canvas_MouseMove">
<Grid>
<!--Would rather not post here for Intellectual Property reasons-->
<!-- Extension of the image control -->
<CustomImageUserControl />
<Grid>
<Grid Width="{Binding LabelWidthPercentage}"
MaxWidth="50"
Height="{Binding LabelHeightPercentage"
MaxHeight="26"
SnapsToDevicePixels="True" VerticalAlignment="Top"
HorizontalAlignment="Left" Margin="5" IsHitTestVisible="False">
<Label Name="lblViewboxLabel" HorizontalAlignment="Left"
Padding="5,5,5,0" Margin="0,5,0,0"
Style="{x:Null}"
Content="{Binding lblContent}" />
</Grid>
<Grid>
<Grid Width="{Binding TextBoxWidthPercentage}"
MaxWidth="156"
Height="{Binding TextBoxHeightPercentage}"
MaxHeight="45"
SnapsToDevicePixels="True" Vertical="Top"
HorizontalAlignment="Right" Margin="5" IsHitTestVisible="False">
<Border Style="{DynamicResource CustomBorder}" />
<Grid>
<Textbox Name="txtViewboxTextBox" Text="{Binding txtViewbox}" />
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
</Canvas>
</Grid>
</Viewbox>
If I am not including something that is needed please let me know and I will update my question. Any help would be greatly appreciated this is now day 4 on this issue sadly :-(
I am not sure why you need so many overlapping Grids, but I hope that I can answer your question nevertheless:
In order to have the label left of the text box and to assign a maximum width to each of these two controls, use a Grid with two columns and set the MaxWidth property for each column. Then, assign the label to the left column (the one with index 0) and assign the text box to the right column (index 1). The corresponding code fragment looks like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="30"/>
<ColumnDefinition MaxWidth="156" MinWidth="30"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" x:Name="lblViewboxLabel" HorizontalAlignment="Left" Foreground="Yellow"
Padding="5,5,5,0" Margin="0,5,0,0"
Style="{x:Null}"
Content="{Binding lblContent}" />
<TextBox Grid.Column="1" x:Name="txtViewboxTextBox" Text="{Binding txtViewbox}" Background="Orange"/>
</Grid>
I also have assigned a MinWidth to the right column; this is necessary to make sure that the text box does not completely disappear if it contains no text.

user interface in .net 4.5 and windows presentation foundation

I am still trying to get my head around wpf ui creation. I have created a user control which has a expander, dockpanel and two comboboxes in the dockpanel with equal width hardcoded in xaml. It looks good during the design time and in runtime as long as the expander widths is unchanged. When the expander header is changed to a longer text the dockpanel streches and the two comboxes remain the same size. They are docked to the right hence there is a lot of gap between two comboxes.
My question, is there a way to equally space the two comboboxes in the dockpanel.
Code:
<DockPanel Height="Auto"
DockPanel.Dock="Top"
HorizontalAlignment="Stretch" Name="lhsInput"
VerticalAlignment="Stretch" Width="Auto"
LastChildFill="False">
<ComboBox Height="23" Name="cboLHSItem"
Width="84" FontWeight="Normal"
Margin="1,0,0,0" Foreground="Black" FontFamily="Tahoma" />
<ComboBox Height="23" DockPanel.Dock="Right"
Name="cboLHSValues" Width="79" FontWeight="Normal"
IsEditable="False" Margin="0,0,1,0" FontFamily="Tahoma"
Foreground="Black" />
</DockPanel>
You could use Grid instead of DockPanel, Sample code below:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ComboBox Height="23" Name="cboLHSItem"
MinWidth="79"
Grid.Column="0"
FontWeight="Normal"
Foreground="Black" FontFamily="Tahoma" />
<ComboBox Height="23" MinWidth="79"
Grid.Column="1"
Name="cboLHSValues" FontWeight="Normal"
IsEditable="False" FontFamily="Tahoma"
Foreground="Black" />
</Grid>
DockPanel may be providing the required Width for its Child elements. However, with Grid and its RowDefinitions and ColumnDefinitions you can specify whether you want "Auto" Width/Height or you want to use whatever is available for Width/Height. The above code specifies to use Whatever width available for the Child element by setting Width to * in ColumnDefinition.
UPDATE
To Understand how different Panels of WPF work, refer to MSDN page: Panels Overview

Using TextWraping within a TextBox, inside a Grid for use within a ListBox in WP7

I am trying to get my data to display properly within a GridLayout, which is to be used as a DataTemplate for an Item within ListBox. Here is the code associated with what I am doing:
<Grid Name="FeedItemTemplate">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Source="{Binding ProfileImage}" Grid.RowSpan="2" Height="75" Width="75" VerticalAlignment="Center" Margin="1" />
<TextBlock Text="{Binding UserName}" Grid.Column="1" Foreground="#FFC8AB14" FontSize="28" HorizontalAlignment="Left"/>
<TextBlock Text="{Binding TimeStamp}" Grid.Column="2" TextWrapping="Wrap" FontSize="18" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Message}" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" TextWrapping="Wrap" FontSize="24" />
</Grid>
The issue is that using this layout, when TextWrapping is set to Wrap, the Item is displayed correctly, but when scrolling through the ListBox everything is really jittery, you cannot scroll in small increments, and it just jumps all over the place.
Any reason why it does this? As I said, only when TextWrapping is set to Wrap it does this. When its not used, it scrolls fine, but the text is all along one line and off the screen.
Does it keep jumping if you explicitly set the top-level Grid element's width to a fixed size?
For some reason that I do not fully understand, settings the ListBox's ItemsPanel property to a StackPanel might solve your problem:
<UserControl.Resources>
<ItemsPanelTemplate x:Key="MyItemsPanelTemplate">
<StackPanel/>
</ItemsPanelTemplate>
</UserControl.Resources>
...
<ListBox ... ItemsPanel="{StaticResource MyItemsPanelTemplate}"/>
This is a known issue with listbox scrolling in the current ctp when you have variable height items. The workaround for now is to set a fixed height on your listbox item content. You'll probably also notice the scroll bar doesnt properly go to the bottom all the time. The workaround fixes that too.
Reference.

Categories