C# WPF - Make Polygon encapsulate text - c#

I'm working on a chat client and I'm having a bit of trouble making it look pretty. I have a polygon defined as this:
<Polygon
Points="0,25 5,27 5,35 200,35 200,15 5,15 5,23 0,25"
Stroke="Purple"
Margin="4, 0, 4, 0">
<Polygon.Fill>
<SolidColorBrush Color="#e4eef2" />
</Polygon.Fill>
</Polygon>
This polygon makes a chat message window similar to the one Skype uses.
A textblock is used directly below it to display the text.
<TextBlock FontSize="14" Width="auto" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="12, 0, 4, 0" TextWrapping="WrapWithOverflow" Text="{Binding text}"/>
If the text is too long and wraps, it falls outside of the polygon. Also, there may be multi-line text, which also falls outside of the polygon. Finally, I'm having trouble getting the polygon to extend the full width of the listitem it is contained in.
The full code is below.
<ListBox Grid.Column="2" Name="MessageList" ScrollViewer.HorizontalScrollBarVisibility="Disabled"> <!-- Messages -->
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel Height="Auto" Width="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" LastChildFill="True">
<Image Visibility="{Binding visibility}" Height="50" Width="50" Stretch="Fill" Source="sampleavatar.png"/>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Polygon
Points="0,25 5,27 5,35 200,35 200,15 5,15 5,23 0,25"
Stroke="Purple"
Margin="4, 0, 4, 0">
<Polygon.Fill>
<SolidColorBrush Color="#e4eef2" />
</Polygon.Fill>
</Polygon>
<TextBlock FontSize="14" Width="auto" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="12, 0, 4, 0" TextWrapping="WrapWithOverflow" Text="{Binding text}"/>
</Grid>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
How a message should look, except it should be more centered
Even less centered text when there's no avatar
Text wrapping, also notice the polygon doesn't shrink horizontally(Nor does it grow horizontally when the listboxitem is bigger)

What you can do, is use a combination of Polygons and a TextBox (read only) to achieve what you want.
The key point here is you want the polygon to grow whenever the text grows/wraps. So to get this to work, we can use a TextBox's border, and a combination of polygons to get the triangle.
See below:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Polygon Grid.Column="0"
x:Name="Polygon"
Points="8,0 0,5, 8,10"
Stroke="Purple"
Fill="#e4eef2"
StrokeThickness="2"
VerticalAlignment="Center"
Margin="2,2,-4,0"/>
<Polygon Grid.Column="1"
Panel.ZIndex="10"
Points="8,0 0,5, 8,10"
Stroke="#e4eef2"
Fill="#e4eef2"
StrokeThickness="2"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="-2.5,2,0,0"/>
<TextBox Grid.Column="1"
Background="#e4eef2"
BorderBrush="Purple"
BorderThickness="2,2,2,2"
VerticalAlignment="Center"
Padding="8,0,8,0"
FontSize="14"
Width="auto"
TextWrapping="WrapWithOverflow"
Text="This is a test"
IsReadOnly="True"/>
</Grid>

Your polygon is not going to shrink horizontally with the text because that is actually a different polygon, I think an option is to scale the polygon horizontally or vertically or both which might require some IValueConverters.
Start with this,
<Border VerticalAlignment="Center" BorderThickness="0,1,1,1" BorderBrush="Purple" CornerRadius="5">
<TextBlock x:Name="textBlock"
FontSize="14" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="12, 0, 0, 0" TextWrapping="WrapWithOverflow" Text="blah blah blah blah blah blah blah blah blah "/>
</Border>
Then add your curly thing to the left side.

Related

How to add a separator to the Expander component in UWP app?

I'm looking for a way of implementing this kind of separator to the expander component in UWP app:
Any ideas how to do that?
I've managed to create the similar look of the expander, but I don't know how to implement separators?
Also, I would like to learn how to make expanders kind of "push" other components down when I expand them, so they don't overlap with other components, but simply move them.
Here's the XAML code for this expander:
<muxc:Expander x:Name="FontExpander"
x:Uid="FontExpander"
Width="1155"
IsExpanded="True"
Margin="22,323,0,0"
VerticalAlignment="Top"
Grid.Row="2"
Height="380"
HorizontalContentAlignment="Left"
ExpandDirection="Down">
<muxc:Expander.Header>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<FontIcon Margin="0,0,12,0"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
FontSize="16"
Glyph=""/>
<StackPanel Grid.Column="1"
Margin="0,12"
Orientation="Vertical">
<TextBlock x:Uid="SettingsFontTitle" Style="{StaticResource BodyTextBlockStyle}"/>
<TextBlock x:Uid="SettingsFontDescription"
Style="{StaticResource CaptionTextBlockStyle}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
TextWrapping="WrapWholeWords"/>
</StackPanel>
</Grid>
</muxc:Expander.Header>
<muxc:Expander.Content>
<Grid Margin="-18,-170,-17,-170">
<TextBlock x:Name="SettingsFamily" x:Uid="SettingsFamily" Text="Family" Margin="50,51,1000,286"/>
<ComboBox x:Name="ComboBoxFamily" ItemsSource="{x:Bind Fonts}" Width="200" Margin="950,41,0,0" SelectionChanged="ComboBoxFamily_SelectionChanged" />
<TextBlock x:Name="SettingsStyle" x:Uid="SettingsStyle" Text="Style" Margin="50,106,995,218" Loaded="SettingsStyle_Loaded"/>
<ComboBox x:Name="ComboBoxStyle" Width="200" Margin="950,101,0,0">
<x:String>Regular</x:String>
</ComboBox>
<TextBlock x:Name="SettingsSize" x:Uid="SettingsSize" Text="Size" Margin="50,166,1002,158"/>
<ComboBox x:Name="ComboBoxSize" ItemsSource="{x:Bind FontSizes}" Width="200" Margin="950,161,0,0"/>
<TextBlock x:Name="Text" x:Uid="SettingsText" Text="Hello World! I am so excited to be here!" Margin="62,224,38,126" TextWrapping="Wrap" FontSize="{x:Bind (x:Double)ComboBoxSize.SelectedValue, Mode=OneWay}" TextAlignment="Center"/>
</Grid>
</muxc:Expander.Content>
</muxc:Expander>
Any help would be much appreciated!
A separate can for example be implemented using a Border or a Grid:
<Grid Background="DarkGray" Height="1" />
As a side note, you shouldn't use margins to position your elements. Use an appropriate layout Panel. Using a Grid, you should add ColumnDefinitions and RowDefinitions to it as examplified here.

How to align labels properly in a stack panel

I'm trying to achieve something like this:
As you can see there is a title "This is what I want" that is aligned with
another label
Code that I wrote:
<Grid Width="345" Height="445" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Vertical" Margin="10">
<Label Content="How to align this to the left:" />
<StackPanel Grid.Row="1" Orientation="Horizontal" Background="#D9D9D9">
<Label Content="€" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" />
<Label Content="256,00" FontSize="38" FontWeight="Bold" />
</StackPanel>
</StackPanel>
</Grid>
</Grid>
And results of my code looks like this:
As it is possible to notice, label is not aligned to the left, looks like there is some padding or something...
And also € sign is not on a right place, I tried to achieve this like it's on first image, but everything I tried with different types of aligns (horizontal, centered) did not work..
Thanks guys
Cheers
Set the Padding of the Label to 0 or use a TextBlock. A TextBlock is more light-weight than a Label and it has no default Padding.
And you can use the Margin property to move the €-sign up a bit:
<StackPanel Grid.Row="0" Orientation="Vertical" Margin="10">
<TextBlock Text="How to align this to the left:" />
<StackPanel Grid.Row="1" Orientation="Horizontal" Background="#D9D9D9">
<TextBlock Text="€" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Bottom"
Margin="0 0 3 5"/>
<TextBlock Text="256,00" FontSize="38" FontWeight="Bold" />
</StackPanel>
</StackPanel>

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.

Stackpanel: Black background on wp8

I have one problem - my stackpanel is vey big and it breaks(background color is changed to black).. What should i do to improve it?
<Grid x:Name="LayoutRoot" Background="#FF2D2D2D" >
<Grid.RowDefinitions>
<RowDefinition Height="60"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Orientation="Horizontal" Grid.Row="0">
..
</StackPanel>
<ScrollViewer Name="viewer" Grid.Row="1" >
<StackPanel Name="ContentGrid" Canvas.ZIndex="1" Margin="0, 0,0,80" Background="White" Width="452">
<Image Name="ImageImage" Height="300" VerticalAlignment="Top"/>
<TextBlock Name="DateText" TextWrapping="Wrap" TextAlignment="Center" FontSize="18" Foreground="Black"/>
<TextBlock Name="TitleText" TextWrapping="Wrap" FontSize="20" TextAlignment="Center" Foreground="Black" Margin="10,0"/>
<TextBlock TextWrapping="Wrap" Margin="10,15,10,2" Name="DescroptionText" FontSize="23" Foreground="#FF494949" FontFamily="Portable User Interface"/>
<TextBlock TextWrapping="Wrap" TextTrimming="WordEllipsis" Margin="10,0,10,2" Name="DescroptionText2" FontSize="23" Foreground="#FF494949"/>
<ListBox SelectionChanged="GridImages_SelectionChanged" ScrollViewer.VerticalScrollBarVisibility="Disabled" Name="GridImages" ItemTemplate="{StaticResource AttachmentsItemTemlate}" Grid.RowSpan="2" FontFamily="Portable User Interface" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal" FlowDirection="LeftToRight" ItemWidth="150" ItemHeight="150"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</StackPanel>
</ScrollViewer>
</Grid>
There is a limitation of 2048px in Windows Phone UIElements.
You should try to break your different elements into smaller elements (for example: you could put several stackpanels inside the first one).
In TextBox elements there is a workaround explained here.
Best this is to make the Main Window to white background and Make your stackpanel as transparent background instead of giving any color to it. It works great as I have tested it.
Try this code, but first you need to add windows toolkit library.
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
<toolkit:PhoneTextBox
TextWrapping="Wrap"
Name="txtString"
ScrollViewer.VerticalScrollBarVisibility="Visible"
MaxHeight="200"
PlaceholderText="Add text"
Padding="5"
Width="370"
FontFamily="Open Sans Light"
FontSize="22"
Height="Auto" ///Use Auto or provide height value
Margin="10"
/>
This code is used for Scrolling as well work for Auto Growing Textbox. If you don't want Auto Growing Textbox then provide height instead of Auto in Height attribute.

Auto-sizing multiple TextBox(es) within a DockPanel

I was hoping someone could help me out here. I have 2 textboxes and a button within a dockpanel and I would like to get the 2 textboxes to stretch and shrink based on window size.
I have a dockpanel which contains a bunch of menu buttons on the left and within this dock I have another dock with 2 textboxs and a button. When I resize the main window, I would like the right dock to shrink the textboxes so that the right dock just doesn't dissapear when hit against the left dock. Does this make sense?
<DockPanel LastChildFill="False">
<Button DockPanel.Dock="Left" Margin="5, 0, 0, 0" Name="button1" Content="1" FontSize="10" Foreground="#FF565656" Width="64" Height="40"/>
<Button DockPanel.Dock="Left" Margin="5, 0, 0, 0" Name="button2" MinWidth="25" />
<DockPanel LastChildFill="False" DockPanel.Dock="Right" Margin="5, 0, 5, 0">
<TextBox DockPanel.Dock="Left" Name="textBoxUsername" Text="" TextWrapping="Wrap" ToolTip="Enter username" FontSize="11" FontWeight="Normal" Height="20" HorizontalAlignment="Left" Width="90" d:LayoutOverrides="GridBox" KeyUp="textBoxUsername_KeyUp" />
<PasswordBox Margin="5, 0, 0, 0" DockPanel.Dock="Left" Name="textBoxPassword" ToolTip="Enter password" Height="20" d:LayoutOverrides="HorizontalAlignment, GridBox" Width="90" KeyUp="textBoxPassword_KeyUp" />
<Button DockPanel.Dock="Left" Margin="5, 0, 0, 0" Name="buttonLogin" Content="Login" Height="20" MinWidth="70" Click="buttonLogin_Click" Width="500" />
</DockPanel>
</DockPanel>
This currently will just have the right dockpanel dissapear all together when the window is resized below the width of everything in the panel. I would like to have the right panel (the embedded dockpanel) shrink in size. Is this possible without a huge re-write effort? I obviously left a lot of the code out... Any help would be appreciated.
UPDATE
I am getting closer, but still not quite what I was hoping for. I added a grid, this allows the stretching, but I was hoping to leave everything stationary to the right. Meaning, I only want to shrink, not stretch but it be pinned to the right.
Here is the what it looks like now.
<DockPanel LastChildFill="False">
<Button DockPanel.Dock="Left" Margin="5, 0, 0, 0" Name="button1" Content="1" FontSize="10" Foreground="#FF565656" Width="64" Height="40"/>
<Button DockPanel.Dock="Left" Margin="5, 0, 0, 0" Name="button2" MinWidth="25" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" MaxWidth="110" />
<ColumnDefinition Width="*" MaxWidth="110" />
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox Name="textBoxUsername" Text="" TextWrapping="Wrap" ToolTip="Enter username" FontSize="11" FontWeight="Normal" FontStyle="Normal" Foreground="#FF9C9C9C" FontFamily="Arial Unicode MS" Height="20" d:LayoutOverrides="GridBox" KeyUp="textBoxUsername_KeyUp" Margin="5,13,5,0" MaxWidth="110" VerticalAlignment="Center" HorizontalAlignment="Stretch" />
<PasswordBox Grid.Column="1" Margin="5,13,5,0" Name="textBoxPassword" ToolTip="Enter password" Height="20" d:LayoutOverrides="HorizontalAlignment, GridBox" KeyUp="textBoxPassword_KeyUp" MaxWidth="110" VerticalContentAlignment="Center" />
<Button Grid.Column="2" DockPanel.Dock="Left" Margin="5,13,5,0" Name="buttonLogin" Content="Login" Template="{StaticResource ButtonControlTemplate2}" FontFamily="Arial" BorderBrush="{x:Null}" Background="{x:Null}" Height="20" MinWidth="70" Click="buttonLogin_Click" />
</Grid>
</DockPanel>
So this is centering everything within the the space it has. As soon as I put the horizontal alignment to "Right", the textboxes get crushed like this
Any thoughts on this?
This is happening because of the precedence of the textbox content. The TextBox's own width will be always equal to its content, so if you want some textboxes to have a different value, you should either set their Width property or set their parent's Width property.
You might me interested in a solution either this:
<TextBox Name="textBoxUsername" Width="100" ... />
Or this:
...
<ColumnDefinition Width="110" />
<ColumnDefinition Width="110" />
<ColumnDefinition Width="100" />
...
Or even this:
<TextBox Name="textBoxUsername" MinWidth="100" ... />
Note the MinWidth property.

Categories