How to make WPF label side by side? - c#

I am trying to put 2 label in stackpanel (Which is in grid) side by side but it's not wokring. the 2nd label come to the 2nd line.
I tried 2 textblock in content property but it doesn't work. I try settting Orientation and ContentAlignment mention in stackoverflow doesn't make any changes.
The first label is bold and another one is normal. Anyone have any idea how to make it work.
Here is the code.
<Label Style="{StaticResource FormHead}">
<Label.Content>
<TextBlock>aaa</TextBlock>
<TextBlock>bbb</TextBlock>
</Label.Content>
</Label>

You can simply do it as below :
<StackPanel Orientation="Horizontal">
<TextBlock>aaa</TextBlock>
<TextBlock>bbb</TextBlock>
</StackPanel>

Try this.
<Label>
<Label.Content>
<StackPanel Orientation="Horizontal">
<TextBlock>aaa</TextBlock>
<TextBlock>bbb</TextBlock>
</StackPanel>
</Label.Content>
</Label>

Related

WPF C# - TextBlock inside custom ProgressBar not showing [duplicate]

This may be a no-brainer for the WPF cognoscenti, but I'd like to know if there's a simple way to put text on the WPF ProgressBar. To me, an empty progress bar looks naked. That's screen real estate that could carry a message about what is in progress, or even just add numbers to the representation. Now, WPF is all about containers and extensions and I'm slowly wrapping my mind around that, but since I don't see a "Text" or "Content" property, I'm thinking I'm going to have to add something to the container that is my progress bar. Is there a technique or two out there that is more natural than my original WinForms impulses will be? What's the best, most WPF-natural way to add text to that progress bar?
Both of the prior responses (creating a new CustomControl or an Adorner) are better practices, but if you just want quick and dirty (or to understand visually how to do it) then this code would work:
<Grid Width="300" Height="50">
<ProgressBar Value="50" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
My Text
</TextBlock>
</Grid>
Just keep in mind that the z-index is such that the last item listed will be on top.
Also, if you don't have Kaxaml yet, be sure to pick it up - it is great for playing with XAML when you're trying to figure things out.
This can be very simple (unless there are alot of ways getting this to work).
You could use Style to get this done or you just overlay a TextBlock and a ProgressBar.
I personally use this to show the percentage of the progress when waiting for completion.
To keep it very simple I only wanted to have one Binding only,
so I attached the TextBock.Text to the ProgressBar.Value.
Then just copy the Code to get it done.
<Grid>
<ProgressBar Minimum="0"
Maximum="100"
Value="{Binding InsertBindingHere}"
Name="pbStatus" />
<TextBlock Text="{Binding ElementName=pbStatus, Path=Value, StringFormat={}{0:0}%}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
Here is how this could look like:
Check out WPF Tutorial for the full post.
If you are needing to have a reusable method for adding text, you can create a new Style/ControlTemplate that has an additional TextBlock to display the text. You can hijack the TextSearch.Text attached property to set the text on a progress bar.
If it doesn't need to be reusable, simply put the progress bar in a Grid and add a TextBlock to the grid. Since WPF can compose elements together, this will work nicely.
If you want, you can create a UserControl that exposes the ProgressBar and TextBlock as public properties, so it would be less work than creating a custom ControlTemplate.
You could use an Adorner to display text over top of it.
See MSDN article on Adorners
You would create a class that inherits from the Adorner class. Override the OnRender method to draw the text that you want. If you want you could create a dependency property for your custom Adorner that contains the text that you want to display. Then use the example in the link I mentioned to add this Adorner to your progress bar's adorner layer.
ProgressBar with Text and Binding from 2 Properties ( Value/Maximum value ):
<Grid>
<ProgressBar Name="pbUsrLvl"
Minimum="1"
Maximum="99"
Value="59"
Margin="5"
Height="24" Foreground="#FF62FF7F"/>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Text>
<MultiBinding StringFormat="{}UserLvl:{0}/{1}">
<Binding Path="Value" ElementName="pbUsrLvl" />
<Binding Path="Maximum" ElementName="pbUsrLvl" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Grid>
Rezult:
The same but with % of progress :
<Grid>
<ProgressBar Name="pbLifePassed"
Minimum="0"
Value="59"
Maximum="100"
Margin="5" Height="24" Foreground="#FF62FF7F"/>
<TextBlock Text="{Binding ElementName=pbLifePassed, Path=Value, StringFormat={}{0:0}%}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
Right click ProgressBar, and click Edit Template > Edit a Copy.
Then put the TextBlock as shown below just above the closing tag of Grid in the Style generated by VS.
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"/>
<TextBlock Background="Transparent" Text="work in progress" Foreground="Black" TextAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
This is based on the given answers.
Since I´m using MahApps Metro, I ended up with this:
<Grid>
<metro:MetroProgressBar x:Name="pbar" Value="50" Height="20"></metro:MetroProgressBar>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ElementName=pbar, Path=Value, StringFormat={}{0:0}%}"></TextBlock>
</Grid>
If you want to use the normal bar with Metro Style:
<Grid>
<ProgressBar x:Name="pbar" Value="50" Height="20" Style="{StaticResource MetroProgressBar}"></ProgressBar>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ElementName=pbar, Path=Value, StringFormat={}{0:0}%}"></TextBlock>
</Grid>
Same without Style:
<Grid>
<ProgressBar x:Name="pbar" Value="60" Height="20" Style="{x:Null}"></ProgressBar>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding ElementName=pbar, Path=Value, StringFormat={}{0:0}%}"></TextBlock>
</Grid>
What is Happening?
You have your progressbar and simply just lay text over it.
So you just use your progressbar as you would.
Put the progressbar in a grid and lay an textblock in it.
Then you can text as you wish or grab the current percenteage wich is the value from the progressbar.

Formatting Label Content Font

I've been trying to change the FontWeight of a single Label inside of a StackPanel of labels to no avail. In the example below, I try to change the FontWeight inline with the Label definition, but this does not work. I can't seem to change the FontWeight, FontSize, FontStyle, etc. I have been able to change the Foreground though.
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center"
DataContext="{Binding Path=MyDataContext}" Grid.Column="1" Grid.Row="4" >
<Label Content="{Binding Path=Label1Content}" FontWeight="Bold"></Label>
<Label Content="{Binding Path=Label2Content}"></Label>
<Label Content="{Binding Path=Label3Content}" ContentStringFormat="c"></Label>
<Label Content="{Binding Path=Label4Content}" ContentStringFormat="c"></Label>
</StackPanel>
I have also tried creating a resource and using a style to do it and have tried changing the FontWeight using the code behind, neither worked.
Further looking in the Live Property Inspector, even though the Label was bold, there was a TextBlock inside that was not. Changing the labels to the following code fix this:
<Label>
<TextBlock Text="{Binding Path=Label1Content}" FontWeight="Bold"></TextBlock>
</Label>

How do I keep a specific xaml element within the window (so it doesn't overflow through the bottom)

I'm trying to make a simple invoicing application as part of an assessment. I have made a interface with a listbox that contains all the items that have been requested. However when I add too many items, the listbox then flows through the bottom of the window and I have to resize the window to fit.
I've tried a dockpanel, and I've assigned the stackpanel to the grid itself. If I set a fixed height it seems to work as expected.
Here is the xaml of the listbox:
<StackPanel Grid.Column="1" Grid.Row="0" ClipToBounds="True">
<ListBox Name="Shirts" HorizontalContentAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Visible" Margin="5" ClipToBounds="True">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding ShirtSize}" />
<Run Text="{Binding ShirtStyle}" />
<Run Text="{Binding ShirtColour}" />
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Print Invoice" Margin="5" ClipToBounds="True"/>
</StackPanel>
I expected the code to work like this (it's not meant to be of fix height but it works as an example).
How it actually works.
Use a DockPanel instead of a StackPanel and it should work better. StackPanel will grow with its content regardless of its container size. A DockPanel will respect the container size and fill the available space. Put the button first in order with Dock="Bottom" and then the ListBox with Dock="Fill" (the list will arrange itself above the button even though it is declared after it, which is a bit unintuitive)

Binding textblock text from resources wpf

<Grid.Resources>
<DataTemplate x:Key="trackTemplateY">
<TextBlock x:Name="txbValueY" Text="{Binding ValueX}" Margin="5" FontSize="11" FontWeight="Medium"/>
</DataTemplate>
</Grid.Resources>
<TextBlock Text="{Binding ElementName=txbValueY,Mode=OneWay,Path=Text}"
Background="Orange" Foreground="White"/>
I try this above code but i cant to bind the text, how can i bind inside resources textblock text to outside the resources, Thanks
I am guessing that you are trying to show Text present in TextBlock resource in your second non-resource TextBlock.
You don't need DataTemplate. As you will progress ahead in WPF journey, you will come to know about those.
Below code will show "Resource Text" in your second TextBlock.
<Grid.Resources>
<TextBlock x:Key="TbRes1" Text="Resource Text" x:Name="txbValueY" Margin="5" FontSize="11" FontWeight="Medium"/>
</Grid.Resources>
<TextBlock Text="{Binding Source={StaticResource TbRes1},Mode=OneWay,Path=Text}"
Background="Orange" Foreground="White"/>
All sorts of problems here:
You're specifying Mode.TwoWay in your TextBlock Text binding, it should be Mode.OneWay.
You're binding to the Label's Text property. Label doesn't have a Text property, only Content. And it's not a dependency property so you can't bind to it. (That said, a fluke of the internal mechanics does cause it to appear to work under certain conditions).
A template is exactly that: a template. You can't bind to something that doesn't exist, so the binding is meaningless.
Maybe you could clarify exactly what it is you're trying to do so we can suggest an alternative way of achieving it? Specifically, show us exactly how you're instantiating that DataTemplate.
UPDATE:
You need the first textbox to be created in order for the second one to bind to it, simply declaring it inside a DataTemplate doesn't cause that to happen by itself, so the direct binding will fail. Binding UI elements together like this should generally be avoided though, why can't you simply give the second textbox the same binding as the first?
<Grid>
<Grid.Resources>
<DataTemplate x:Key="trackTemplateY">
<TextBlock x:Name="txbValueY" Text="{Binding ValueX}" Margin="5" FontSize="11" FontWeight="Medium"/>
</DataTemplate>
</Grid.Resources>
<TextBlock Text="{Binding ValueX}" Background="Orange" Foreground="White"/>
</Grid>
If for some reason this isn't possible then you can also create a binding proxy object (see this page for details):
<Grid>
<Grid.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding ValueX}" />
<DataTemplate x:Key="trackTemplateY">
<TextBlock x:Name="txbValueY" Text="{Binding ValueX}" Margin="5" FontSize="11" FontWeight="Medium"/>
</DataTemplate>
</Grid.Resources>
<TextBlock Text="{Binding Source={StaticResource ResourceKey=proxy}, Path=Data}" Background="Orange" Foreground="White"/>
</Grid>
Again, there are ways to bind to the data template declaration if you really want to, but to do that I'd have to see details of how your data template is being created at runtime.

Silverlight Tooltip Remain Visible With Mouseover

Hello and thanks for the help. I have a Treeview that I am populating with a Hierarchical data template, and currently the bottom nodes have a tooltip that generates a small stack panel that is populated with data specific to the item the mouse hovers over. I also have a button sitting in the tooltip, however, as the tooltip does not persist when the mouse moves over it, I am unable to make use of the button like I need to. My xaml looks like this:
<!--=========================== Hierarchical Data template for tree view -->
<!--template for bottom nodes-->
<sdk:HierarchicalDataTemplate x:Key="ModTemplate" ItemsSource="{Binding ApplicationModules}">
<StackPanel Orientation="Horizontal" > <!--======tooltip style to handle format for callout window============-->
<ToolTipService.ToolTip>
<ToolTip HorizontalOffset="0" VerticalOffset="0" Style="{StaticResource ModuleToolTipStyle}">
<StackPanel Width="150" Height="auto" >
<TextBlock Text="Module Info" FontWeight="Bold" TextAlignment="Center"/>
<TextBlock Text="Module State:" FontWeight="Bold" />
<TextBlock Text="{Binding Path=ModInfo.ModuleState}" />
<TextBlock Text="Module Start Time:" FontWeight="Bold" />
<TextBlock Text="{Binding Path=ModInfo.ModuleStartTime}"/>
<TextBlock Text="Module Down Time:" FontWeight="Bold"/>
<TextBlock Text="{Binding Path=ModInfo.ModuleDownTime}" />
<Button Content="More Info" Width="75"></Button>
</StackPanel>
</ToolTip>
</ToolTipService.ToolTip>
<!--============end tooltip style for callout window===================-->
<ContentPresenter Margin="0 0 4 0" Content="{Binding Icon}" />
<TextBlock FontStyle="Italic" Text="{Binding Path=ModuleName}" />
</StackPanel>
</sdk:HierarchicalDataTemplate>
I would like the tooltip to persist when the mouse moves over it so that I can wire an event to the button. How can I achieve this? Thanks again for the help.
You have a couple options to accomplish your goal that I'm aware of. You can go check out the Silverlight Advanced Tooltips project over on codeplex which does what you want (though I personally have not used it so can't give any kind of review.)
Or you can make your own with some creativity. If it were me I would probably skip all that mess, forget the ToolTipService all together and just make my own to dress it up since to a user, what you're providing isn't what they're used to in terms of a tooltip expectation anyway and have cross more over to a callout or popout functionality. I can make an example as soon as I get some freed up time if option #1 doesn't work for you but I hope it does. Essentially both my way, and that project link I provided would do the same thing, which is provide a delay after the MouseLeave event of what it's attached to so the user can get to it before it disappears. Then hand off its visibility condition to that object. Let me know if this doesnt work and I can give you an alternative example using nothing but XAML.

Categories