Status bar in wpf - wpf

<StatusBar Height="20" Grid.ColumnSpan="4" HorizontalAlignment="Left" Name="statusBar1" VerticalAlignment="Bottom" Width="1533" Background="AntiqueWhite">
<TextBlock >HName:</TextBlock>
<TextBlock Name="hname" Text="{Binding Path=CHost}"></TextBlock>
<Separator/>
<TextBlock >P:</TextBlock>
<TextBlock Name="p" Text="{Binding Path=CPort, TargetNullValue=6130,UpdateSourceTrigger=PropertyChanged}"></TextBlock>
<Separator/>
<TextBlock Name="cstatus">CStatus:</TextBlock>
<TextBlock x:Name="CoStatus" Text="{Binding Path=CStatus, NotifyOnSourceUpdated=True,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"></TextBlock>
<Separator/>
<TextBlock AllowDrop="False" Name="sock1">CSock:</TextBlock>
<TextBlock x:Name="CoName" Text="{Binding Path=CoName,NotifyOnSourceUpdated=True, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"></TextBlock>
<Separator x:Name="seperator1" Margin="520,0,0,0"/>
<TextBlock >HName:</TextBlock>
<TextBlock Name="hname1" Text="{Binding Path=CHost1}"></TextBlock>
<Separator/>
<TextBlock >P:</TextBlock>
<TextBlock Name="p1" Text="{Binding Path=CPort, TargetNullValue=6130,UpdateSourceTrigger=PropertyChanged}"></TextBlock>
<Separator/>
<TextBlock Name="cstatus1">CStatus:</TextBlock>
<TextBlock x:Name="CStatus1" Text="{Binding Path=CStatus1, NotifyOnSourceUpdated=True,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"></TextBlock>
<Separator/>
<TextBlock AllowDrop="False" Name="sock2">Sock1:</TextBlock>
<TextBlock x:Name="CoName1" Text="{Binding Path=CoName1,NotifyOnSourceUpdated=True, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"></TextBlock>
</StatusBar>
I have added this status bar in my main window and placed bottom of my screen. I have control inside that to show some text with value.
I have to show information of Hname, P, CStatus and sock for two different client on same status bar of main window.
So I have used for making space between them.
But what I want when My application first time launch after all information should not be visible when I'm connect my second client then this part come but there should be enough space between them so that Screen look good.
Width and height of status bar is 1533 and 20 respectively. I tried to put two child status bar for two different client on status bar but SomeHow It didn't work. Please suggest how to do this

One solution is to use grid inside the statusbar like this:
<StatusBar HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch">
<StatusBarItem HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" >
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
...
</Grid.ColumnDefinitions>
<!-- Content goes here using the grid -->
<Grid/>
<StatusBarItem/>
<StatusBar/>
Or use an itemtemplate for the status bar like this:
<StatusBar Height="40">
<StatusBar.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition MaxWidth="100" />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
<StatusBarItem Grid.Column="0">
<!-- content... -->
</StatusBarItem>
<StatusBarItem Grid.Column="1">
<!-- content -->
</StatusBarItem>
<StatusBarItem Grid.Column="2" Visibility="{Binding IsSomePropertyVisible, Converter={StaticResrouce BooleanToVisibilityConverter}}">
<!-- content -->
</StatusBarItem>
....
</StatusBar>
Use a IValueConverter to determine what parts of your statusbar that should be visible or not. Beware of setting explicit sizes now! Typically you want some property that's a bool which tells if the user is logged in or not, and just bind to that property and use a BooleanToVisbilityConverter.
You may also dump the template for the control and disassemble it, to see how it works internally.
Hope it helps,
Cheers
Stian

Related

How to center UserControl in a TabControl

My MainWindow is built with TabContol containing in each tab UserControl in xaml files. Opening specific UserControl is not a problem, but aligning it is. I was able to horizontally center content of tab but struggle to vertically do this same. I found out that the root problem is that UserControl don't take the whole free space (height) in the Tab. I tried to make main grid VerticalAlignment="Stretch" and "Center" but that didn't help. I could use margin with specific number or define row fixed hight but that will not work on every resolution and I don't want to write method in code behind but use the power of xaml. How can I force UserControl to take whole height in Tab and then vertically center it (it's important to do it for specific UserControl because others should have default position)?
ps. I'm using MetroWindow from MahApps.Metro.
MainWindow main Grid:
<Grid>
<StackPanel>
<TabControl ItemsSource="{Binding Tabs}"
SelectedIndex="0">
<TabControl.Resources>
<Style TargetType="{x:Type TabPanel}">
<Setter Property="HorizontalAlignment"
Value="Center" />
</Style>
<DataTemplate DataType="{x:Type VMod:LoginViewModel}">
<Pages:LoginView />
</DataTemplate>
<DataTemplate DataType="{x:Type VMod:AdminViewModel}">
<Pages:AdminView />
</DataTemplate>
<DataTemplate DataType="{x:Type VMod:ProductsViewModel}">
<Pages:ProductsView />
</DataTemplate>
<DataTemplate DataType="{x:Type VMod:DistributionViewModel}">
<Pages:DistributionView />
</DataTemplate>
<DataTemplate DataType="{x:Type VMod:SummaryViewModel}">
<Pages:SummaryView />
</DataTemplate>
<DataTemplate DataType="{x:Type VMod:SettingsViewModel}">
<Pages:SettingsView />
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type inter:ITab}">
<TextBlock>
<Run Text="{Binding TabName}" />
</TextBlock>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
</StackPanel>
</Grid>
UserControl main Grid:
<Grid Background="LightBlue"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Height="300"
Width="300"
Grid.Row="2"
BorderBrush="LightGray"
BorderThickness="1">
<StackPanel HorizontalAlignment="Center">
<iconPacks:PackIconRPGAwesome Kind="Honeycomb"
HorizontalAlignment="Center"
Width="60"
Height="60"
Margin="0, 0, 0, 0"/>
<TextBlock HorizontalAlignment="Center"
Text="DistributionTool"
FontSize="20"
FontWeight="Bold"
Margin="5" />
<Grid Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0"
Margin="5"
TextAlignment="Left"
FontSize="15"/>
<iconPacks:PackIconMaterial Grid.Column="1"
Kind="AccountTie"
Width="20"
Height="20"
VerticalAlignment="Center"/>
</Grid>
<Grid Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<PasswordBox Grid.Column="0"
Margin="5"
HorizontalContentAlignment="Left"
FontSize="15"
Style="{StaticResource Win8MetroPasswordBox}" />
<iconPacks:PackIconMaterial Grid.Column="1"
Kind="Key"
Width="20"
Height="20"
VerticalAlignment="Center" />
</Grid>
<Button Content="LOGIN"
Width="80"
metro:ControlsHelper.ContentCharacterCasing="Normal"
Margin="5"
Style="{StaticResource AccentedSquareButtonStyle}" />
</StackPanel>
</Border>
</Grid>
From what I gather, what you could try would be:
Remove the StackPanel in your MainWindow Grid. Unless you intend to have more than 1 child inside the stack panel (Other than your TabControl), it is useless.
Add VerticalAlignement="Stretch" to your TabControl. This will allow it to take up all the space it can vertically.
Then you should be pretty much set to go.
The reason why you shouldn't use a StackPanel unless you intend to stack items inside, as in
<StackPanel>
<Child1/>
<Child2/>
</StackPanel>
is that the StackPanel.Orientation property affects how things will appear inside, including the Alignement of each child.
So Orientation="Vertical" (the default), affects the VerticalAlignement of its children. Same idea with Horizontal.

Why doesn't a textbox stretch inside stackpanel WPF?

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="49*" />
<ColumnDefinition Width="25*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1" Margin="30" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,5,0" Text="Username:" />
<TextBox HorizontalAlignment="Stretch"/>
</StackPanel>
</StackPanel>
--Result image--
Im trying to make it so that the textbox will fill the rest of the space inside the current StackPanel.
however the "Stretch" propety doesn't seem to work - why is that?
Is there a different way do it or what am I doing wrong?
A StackPanel always tries to achieve the minimum possible height/width, depending on orientation; therefore, Stretch has no effect. You might want to use a DockPanel instead, which allows children to stretch:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25*" />
<ColumnDefinition Width="49*" />
<ColumnDefinition Width="25*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1"
Margin="30"
VerticalAlignment="Center">
<DockPanel>
<TextBlock DockPanel.Dock="Left" Margin="0,0,5,0"
Text="Username:" />
<TextBox HorizontalAlignment="Stretch"/>
</DockPanel>
</StackPanel>
</Grid>

WPF - Get value of listbox Data Template item

I have a WPF listbox whose items are defined by a Data Template that consists of a horizontally aligned grid which holds a label and button. When the button is clicked, I would like to pass the label text as a parameter. For the CommandParameter, is there a Binding that I can specify to get the text value of the label?
<ListBox.ItemTemplate>
<DataTemplate >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="114*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1000"/>
<ColumnDefinition Width="100*"/>
<ColumnDefinition Width="200*"/>
</Grid.ColumnDefinitions>
<Label x:Name="JobFileNameLabel" Grid.Column="0" Content="{Binding JobFileName}" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="36" FontWeight="Bold" Padding="0"/>
<Button Command="{Binding DataContext.PrintJobBtnClickedCommand,RelativeSource={RelativeSource AncestorType=ListBox}}" Grid.Column="1" Content="Print" HorizontalAlignment="Center" Margin="25,19,23,25" VerticalAlignment="Center" Width="150" Height="70" RenderTransformOrigin="0.203,-0.173" FontSize="36" FontWeight="Bold" Padding="0"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>

WPF Statusbar, stretch textblock to take as much space as possible

I created my own simple statusbarcontrol with 3 TextBlocks. Now I would like that the first Textblock takes as much space as it has available. That I don't seem to get done.. Now it only takes the space needed to display the text.
XAML:
<StatusBar Background="{StaticResource GradientBrush}">
<StatusBar.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
<StatusBarItem HorizontalAlignment="Left"
HorizontalContentAlignment="Right">
<Border BorderThickness="1"
BorderBrush="Black"
Padding="5 0 5 0"
Background="White">
<TextBlock Text="{Binding Message, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding TextColorMessage}"
Background="White"
/>
</Border>
</StatusBarItem>
<Separator Grid.Column="1" />
<StatusBarItem Grid.Column="2"
HorizontalAlignment="Right">
<TextBlock Text="{Binding Path=DatabaseName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StatusBarItem>
<Separator Grid.Column="3" />
<StatusBarItem Grid.Column="4"
HorizontalAlignment="Right">
<TextBlock Text="{Binding Path=ComputerName}" />
</StatusBarItem>
Well this is pretty straight forward:
you had set the StatusBarItem HorizontalAlignment="Left" when it should be "strech", same for the HorizontalContentAlignment.
Also would suggest setting margin=0 on the border.
this is what i did so it will work for me:
<StatusBarItem HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Border BorderThickness="1"
BorderBrush="Black"
Margin="0"
Padding="5 0 5 0"
Background="White">
<TextBlock Text="{Binding Message, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding TextColorMessage}"
Background="White"/>
</Border>
</StatusBarItem>
if this is helpful please mark as answer
Try setting the StatusBarItem's HorizontalAlignment and HorizontalContentAlignment to Stretch.
Set the StatusBarItem's HorizontalContentAlignment to Stretch and the TextBlock's TextAlignment property to Right. (This second setting is only needed for the first StatusBarItem as it seems that you try to align the text to the right in it.)
StatusBar has only one HorizontalAlignment=Right item to effect, so you can get only the last item in wanted place. You can set statusBar's FlowDirection="RightToLeft" and add item in reversed order. Details: right placed items needn't StatusBarItem surrounded, but the left one need to be streched. Following code:
<StatusBar VerticalAlignment="Bottom" FlowDirection="RightToLeft"><!--flow right to left cause items right aligned-->
<!--make item's flow back left to right, avoid display disorder-->
<TextBlock x:Name="textBlock_status_R1" Text="111.147.168.20" Grid.Column="2" Margin="10,0" FlowDirection="LeftToRight"/>
<Separator/>
<TextBlock x:Name="textBlock_status_R2" Text="Working" Margin="10,0" FlowDirection="LeftToRight"/>
<Separator/>
<!--To fill rest space,need StatusBarItem packing and default HorizontalAlignment="Stretch"-->
<StatusBarItem FlowDirection="LeftToRight">
<TextBlock x:Name="textBlock_status_L1" Text="Information here."/>
</StatusBarItem>
</StatusBar>

StackPanel expanding outside size of parent grid

I'm pretty new with WPF, so apologies if I'm missing something obvious. I have this template that is bound to items in an obs. collection. I'm trying to get it so that the 2nd column, the "test test..." part has a variable width that fills all the available space in the parent grid.
What I'm finding though, is that my code automatically shows all the text for that "test test..." text box as opposed to just binding to the available space in the grid, and instead creates the scroll bar that you see below.
I instead, want that "test test" to be cut off so that everything else fits so that no scroll bar appears (that when, if the user resizes the screen then that "test test..." textbox will automatically resize to fit the new space). Is there a way to do that?
My code for that template is as follows:
<DataTemplate x:Key="MainTemplate">
<Grid Margin="4" ClipToBounds="True">
<Grid.Resources>
<local:BooleanToHiddenVisibility x:Key="boolToVis"/>
</Grid.Resources>
<StackPanel Orientation="Vertical" ClipToBounds="True">
<Grid Width="Auto" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25"/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="60" />
<ColumnDefinition Width="40" />
<ColumnDefinition Width="60" />
<ColumnDefinition Width="40" />
<ColumnDefinition Width="60" />
<ColumnDefinition Width="40" />
<ColumnDefinition Width="40" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" Name="checkViewTextBox"/>
<TextBlock Grid.Column="1" Text="{Binding OriginalQuote}" FontWeight="Bold" TextTrimming="WordEllipsis" FontStyle="Italic" ClipToBounds="True"/>
<TextBlock Margin="10,0,0,0" Grid.Column="2" Text="plane :" FontWeight="SemiBold" Width="60"/>
<TextBlock Margin="5,0,0,0" Grid.Column="3" Text="{Binding Mid}" Width="40"/>
<TextBlock Margin="10,0,0,0" Grid.Column="4" Text="data2 :" FontWeight="SemiBold" Width="60"/>
<TextBlock Margin="5,0,0,0" Grid.Column="5" Text="{Binding MidTwo}" Width="40"/>
<TextBlock Margin="10,0,0,0" Grid.Column="6" Text="data3:" FontWeight="SemiBold" Width="60"/>
<TextBlock Margin="5,0,0,0" Grid.Column="7" Text="{Binding MidThree}" Width="40"/>
<Button Margin="10,0,0,0" Content="History" Grid.Column="8" Click="History_Click" Width="40"/>
</Grid>
<StackPanel Orientation="Horizontal" Visibility="{Binding Path=IsChecked, ElementName=checkViewTextBox, Converter={StaticResource boolToVis}}">
<StackPanel.Resources>
<Style BasedOn="{StaticResource tbstyle}" TargetType="{x:Type TextBlock}" />
</StackPanel.Resources>
<!--Other stuff thats working ok-->
</StackPanel>
</Grid>
</DataTemplate>
Any help is much appreciated!
P.S. I've been adding random proprieties hoping one will work, so if looks like I have random things on there, that's probably why....
Well, not sure it will help you but some words about WPF layout.
It has two steps: measure and arrange.
At the first stage, the control tries to calculate its desired state. StackPanel asks its children about their desired sizes. It does not limit their size. (TextBlock with the binding to OriginalQoute has no explicitly set width!)
At the second stage, control is arranged.
Stack panel is allowed to occupy the whole left space of the column but it arranges its children as if its size was unlimited, so TextBlock shows the text completely.
The question is how to limit the size of the TextBlock?
Try binding
<TextBlock Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel}, Path=ActualWidth}"/>

Resources