I am new to WPF. Is there a possibility that the points of the polyline in XAML
connected in such a way as is possible with the line in the example below.
The same problem is also a mini-language. Thanks
<Line Name="line" Fill="#FFDA2828" Stroke="Black"
X1="{Binding Text, ElementName=textBox1}"
Y1="{Binding Text, ElementName=textBox2}"
X2="{Binding Text, ElementName=textBox3}"
Y2="{Binding Text, ElementName=textBox4}"
Visibility ="Visible" StrokeThickness="2"
StrokeDashArray="2,2,2,2">
</Line>
this will work ,but a converter or a viewmodel is recommended to proxy the binding
anyway I've added a tester
as the text change the line is update
you will get some errors in text-> double conversions
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel>
<TextBox x:Name="TextBox1" Width="100"/>
<TextBox x:Name="TextBox2" Width="100"/>
<TextBox x:Name="TextBox3" Width="100"/>
<TextBox x:Name="TextBox4" Width="100"/>
</StackPanel>
<Canvas Grid.Column="1">
<Line Name="line" Fill="#FFDA2828" Stroke="Black"
X1="{Binding Text, ElementName=TextBox1}"
Y1="{Binding Text, ElementName=TextBox2}"
X2="{Binding Text, ElementName=TextBox3}"
Y2="{Binding Text, ElementName=TextBox4}"
Visibility ="Visible" StrokeThickness="2" StrokeDashArray="2,2,2,2">
</Line>
</Canvas>
</Grid>
Related
I have a similar structure in a WPF app:
<Grid Background="White">
<StackPanel>
<TextBlock Text="1234567" FontSize="18" FontWeight="Bold" Height="25" TextAlignment="Center"/>
<Line X1="0" Y1="0" X2="160" Y2="0" Stroke="Gray" StrokeThickness="2"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Width="25" Height="25" Grid.Column="0" Source="img.png" />
<TextBlock Grid.Column="1" Text="3456789" FontSize="18" FontWeight="Bold" Height="25" TextAlignment="Center"/>
</Grid>
</StackPanel>
This results in the following layout:
Is there any way to place the bottom text in the center of the row, so it's alignment would match with the text above?
Or is there a solution to place the image on top of the bottom row on the left side without column definitions?
Thanks
Use a single-cell grid with different alignments. You will run the risk of long text being under the image, and you will have to set a Width value on the StackPanel. See the HorizontalAlignment flag below:
<Grid>
<TextBlock Text="3456789" FontSize="18" FontWeight="Bold" Height="25" HorizontalAlignment="Center"/>
<Image Width="25" Height="25" Source="img.png" HorizontalAlignment="Left" />
</Grid>
I created the item template control and set its border thickness and color in Data Template. This is my ItemTemplate code:
<ItemsControl x:Name="VimshottariDasha" Margin="-10,83,-124,-267" FontSize="16" Grid.ColumnSpan="3" BorderThickness="0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" BorderBrush="DimGray">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Col1" />
<ColumnDefinition SharedSizeGroup="Col2" />
<ColumnDefinition SharedSizeGroup="Col3" />
</Grid.ColumnDefinitions>
<Button Background="Transparent" BorderThickness="0" x:Name="DashaButton" Grid.Column="0" Content="{Binding rulerName}" Command="{Binding SelectedDasha}" CommandParameter="{Binding Content, RelativeSource={RelativeSource Self}}"/>
<TextBlock Grid.Column="1" Text="{Binding rulerStartDate, StringFormat=dd-MMM-yyyy HH:mm:ss}" />
<TextBlock Grid.Column="2" Text="{Binding rulerEndDate, StringFormat=dd-MMM-yyyy HH:mm:ss}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
How do I show both vertical and horizontal borders regardless of stack orientation?
The same thing happens in another itemTemplate but in reverse, whose stack orientation is set to Horizontal. I can see vertical borders in the second item Control but no Horizontal borders.
This is the current Output, it has horizontal Borders inside but no vertical ones(Stack orientation is vertical by default)
This is second ItemControl with horizontal stack orientation it is missing horizontal borders.
Thanks.
First go through this link to understand how to add border around TextBlock.
You can also use Label instead of TextBlock to add border.
Now look into modified code:
ItemsControl Grid.Row="0" x:Name="VimshottariDasha" Margin="10" FontSize="16" Grid.ColumnSpan="3" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--<Border BorderThickness="1" BorderBrush="DimGray">-->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Col1" />
<ColumnDefinition SharedSizeGroup="Col2" />
<ColumnDefinition SharedSizeGroup="Col3" />
</Grid.ColumnDefinitions>
<Button Background="Transparent" BorderThickness="1" x:Name="DashaButton" Grid.Column="0" Content="{Binding rulerName}" />
<Border Grid.Column="1" BorderThickness="1" BorderBrush="Blue">
<TextBlock Text="{Binding rulerStartDate, StringFormat=dd-MMM-yyyy HH:mm:ss}" />
</Border>
<Label BorderThickness="1" BorderBrush="Bisque" Grid.Column="2" Content="{Binding rulerEndDate, StringFormat=dd-MMM-yyyy HH:mm:ss}"/>
</Grid>
<!--</Border>-->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
A WPF Border control only draws the border along its outer edges. [It is possible to turn of one or more edges by setting its BorderThickness.]
If you want to create border lines between individual controls, you either have to use multiple Border elements, or manually draw the internal lines yourself.
For example
<Border HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="Green" BorderThickness="2" >
<Grid Height="24" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Column 1" VerticalAlignment="Center" />
<TextBlock Grid.Column="2" Text="Column 2" VerticalAlignment="Center" />
<TextBlock Grid.Column="4" Text="Column 3" VerticalAlignment="Center" />
<Path Stroke="Red" StrokeThickness="1" Data="M 0,0 M 2,2 M 1,0 L 1,2" Stretch="Fill" Grid.Column="1" />
<Path Stroke="Red" StrokeThickness="1" Data="M 0,0 M 2,2 M 1,0 L 1,2" Stretch="Fill" Grid.Column="3" />
</Grid>
</Border>
I was wondering if it was possible to do either in WPF:
I guess the main problem here that I can't embed a textblock in a line in XAML, which is something I'm use to doing. Does anyone have any idea of how I can tackle this problem?
EDIT: It would also have to handle diagonal text.
You can do this, this is actually pretty easy. You have to keep in mind that you can nest content inside a <TextBlock> tag....
<TextBlock>
<Line X1="0" Y1="0" X2="100" Y2="0" Stroke="Black" StrokeThickness="4"/>
<TextBlock Text="Hello there!" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Line X1="0" Y1="0" X2="100" Y2="0" Stroke="Black" StrokeThickness="4"/>
</TextBlock>
Could you have a three-column grid, with a line in the first and third column and the text in the second? Of course you’d have to set the left and right line’s properties so that they stretch across the entire width.
I am adding this answer because I found the accepted answer and other answers did not address the first example, with variable length horizontal lines on both sides of Hello. Here is how to do that...
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Separator Grid.Column="0" Margin="5"/>
<TextBlock Text="Hello" Grid.Column="1"/>
<Separator Grid.Column="2" Margin="5"/>
</Grid>
The obvious MaxWidth gets ignored and the text in the "DisplayBox" TextBlock displays the whole text even if this text continues past the parent container controls (to the edge of the silverlight area.
<win:HierarchicalDataTemplate x:Key="hierarchicalTemplate" ItemsSource="{Binding _children}">
<Border BorderThickness="0" BorderBrush="Orange" HorizontalAlignment="Stretch" Background="{Binding Converter={StaticResource BackgroundConverter}}">
<toolkit:DockPanel LastChildFill="True" Width="{Binding HeirarchyLevel, Converter={StaticResource WidthConverter}}" Height="20">
<Canvas toolkit:DockPanel.Dock="Right" Width="20" MouseLeftButtonUp="Arrow_MouseLeftButtonDown">
<Rectangle Width="20" Height="20" Fill="Transparent" />
<Line Stroke="Black" X1="5" Y1="10" X2="17" Y2="10" />
<Line Stroke="Black" X1="11" Y1="5" X2="17" Y2="10" />
<Line Stroke="Black" X1="11" Y1="15" X2="17" Y2="10" />
</Canvas>
<Ellipse Canvas.Top="5" Width="10" Height="10" Fill="Green" toolkit:DockPanel.Dock="Right" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown" />
<Canvas Width="Auto" Loaded="TextArea_Loaded">
<TextBlock Name="DisplayBox" FontFamily="Arial" FontSize="17" Foreground="Black" Width="Auto" Text="{Binding TaskName}" MouseLeftButtonUp="TextBlock_MouseLeftButtonUp" />
<TextBox Name="EditBox" FontFamily="Arial" FontSize="10" Foreground="Black" Height="20" Text="{Binding TaskName}" Visibility="Collapsed" LostFocus="TextBox_LostFocus" />
<Line Stroke="Black" X1="0" Y1="10" X2="202" Y2="10" Width="Auto" />
</Canvas>
</toolkit:DockPanel>
</Border>
</win:HierarchicalDataTemplate>
Can you switch to using a Grid instead of a canvas? A TextBlock will be appropriately clipped when it is a child of a Grid. This is not true of Canvas.
<Canvas Width="Auto" Loaded="TextArea_Loaded">
**<Border>**
<TextBlock Name="DisplayBox" FontFamily="Arial" FontSize="17" Foreground="Black" Width="Auto" Text="{Binding TaskName}" MouseLeftButtonUp="TextBlock_MouseLeftButtonUp" />
<TextBox Name="EditBox" FontFamily="Arial" FontSize="10" Foreground="Black" Height="20" Text="{Binding TaskName}" Visibility="Collapsed" LostFocus="TextBox_LostFocus" />
<Line Stroke="Black" X1="0" Y1="10" X2="202" Y2="10" Width="Auto" />
**</Border>**
</Canvas>
Should also work. (Border will honor label's maxlength. and border itself will not be visible since its thickness is 0.
I am trying to get a layout where an icon floats on the right end of a textblock; the textblock grows/shrinks to content. I cannot make this happen without the textblock running outside the grid. For example:
<Grid x:Name="LayoutRoot" Width="500" HorizontalAlignment="Left" ShowGridLines="True" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="textBlock" VerticalAlignment="Top" Height="25" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" Grid.Column="0" >
<TextBlock.Text>longer keeps going and going testgrand you going and then t
</TextBlock.Text>
</TextBlock>
<Rectangle Fill="#FFDE3030" Stroke="Black" VerticalAlignment="Top" Height="41" Width="41" Grid.Column="1"/>
</Grid>
Seems like the natural approach and works fine when the text is shorter than the column/grid, except the textbox and column will grow indefinitely and not honor the bounds of the grid.
The inverse, with the icon on the left, works fine with a simpler layout, and the textblock doesn’t grow indefinitely. This is achieved with this markup:
<Grid Grid.Row="1" Width="500" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Rectangle Fill="#FFDE3030" Stroke="Black" VerticalAlignment="Top" Height="41" Width="41" Grid.Column="0"/>
<TextBlock x:Name="textBlock2" VerticalAlignment="Top" Height="25" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" Grid.Column="1" HorizontalAlignment="Left">
<TextBlock.Text>longer testgrow the textblock and it will just keep growing but it will stop when it gets too </TextBlock.Text>
</TextBlock>
</Grid>
Any help appreciated. If a grid won’t work, is there an alternate layout where I can get the icon floating on the right of the text, and the textblock will trim text when it’s too long?
Also:
No, using * size columns doesn't work because the columns are fixed, and the icon won't float at the end of the text
A DockPanel doesn't work either, or at least I or others I've asked haven't been able to. The best it can do is to have the icon half-cut-off outside the dockpanel's right side.
Can you get what you want by setting MaxWidth on the TextBlock? If you add MaxWidth="460" to your first example:
<Grid x:Name="LayoutRoot" Width="500" HorizontalAlignment="Left" ShowGridLines="True" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<TextBlock MaxWidth="460" x:Name="textBlock" VerticalAlignment="Top" Height="25" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" Grid.Column="0" >
<TextBlock.Text>longer keeps going and going testgrand you going and then t</TextBlock.Text>
</TextBlock>
<Rectangle Fill="#FFDE3030" Stroke="Black" VerticalAlignment="Top" Height="41" Width="41" Grid.Column="1"/>
</Grid>
Then the TextBlock will grow horizontally and always have the rectangle immediately on its right. It won't be wider than 460, so the TextBlock plus the Rectangle shouldn't be wider than 500. If you need the Grid to resize dynamically then you can bind TextBlock.MaxWidth to Grid.ActualWidth with a converter that subtracts the width of the Rectangle.
Edit:
Actually, it should be even simpler than that. Use star sizing on the columns, but set MaxWidth instead of Width on the Grid. That way, the grid itself will get smaller when the text is smaller so that the rectangle is always at the edge of the text.
<Grid x:Name="LayoutRoot" MaxWidth="500" HorizontalAlignment="Left" ShowGridLines="True" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="textBlock" VerticalAlignment="Top" Height="25" TextWrapping="NoWrap" TextTrimming="CharacterEllipsis" Grid.Column="0" >
<TextBlock.Text>longer keeps going and going testgrand you going and then t</TextBlock.Text>
</TextBlock>
<Rectangle Fill="#FFDE3030" Stroke="Black" VerticalAlignment="Top" Height="41" Width="41" Grid.Column="1"/>
</Grid>
Someone internally suggested this answer, which works:
<WrapPanel HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10" />
</Grid.ColumnDefinitions>
<AccessText TextTrimming="CharacterEllipsis" Grid.Column="0" Margin="0,0,4,0" Text="type more typingon the long hi longer than what if you keep tyingin and get to the end and that's why it changed because you were in the middle" />
<Border Grid.Column="1" Width="10" Height="10" Background="Red" />
</Grid>
</WrapPanel>
The wrappanel seems to provide the necessary magic. I haven't tried Quartermeister's but will save it for future reference!
Our final layout is more complicated and looks like this (it's the header bar for an expander):
<WrapPanel Orientation="Vertical">
<Grid x:Name="HeaderSite" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="19" />
<ColumnDefinition Width="16" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" /> <!-- 7/14: fix from list: wrap the whole thing in a wrappanel. Allows for one * col. -->
<ColumnDefinition Width="19" />
</Grid.ColumnDefinitions>
<ToggleButton x:Name="buttonExpanderToggleButton"
Height="20" VerticalAlignment="Top"
/>
<Image x:Name="imageActivityIcon" Grid.Column="1"
Height="16" Width="16"
HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="0"/>
<AccessText x:Name="textActivityID"
Grid.Column="2"
VerticalAlignment="Top" Margin="5,2,0,0"
TextTrimming="CharacterEllipsis"
FontSize="12" HorizontalAlignment="Left" Text="MA77777"/>
<AccessText x:Name="textActivityHeader"
Grid.Column="3"
VerticalAlignment="Top" Margin="0,2,0,0"
TextTrimming="CharacterEllipsis"
FontSize="12" HorizontalAlignment="Left" Text="Title title title title aand Title title title title a little and if you type more what happens as you keep typing "/>
<AccessText x:Name="textActivityStatus"
FontWeight="Normal"
FontStyle="Italic"
Grid.Column="4"
TextTrimming="CharacterEllipsis"
VerticalAlignment="Top" Margin="0,2,8,0"
FontSize="12" HorizontalAlignment="Left" Text="(On Hold)"/>
<Image x:Name="imageLink"
Stretch="None" VerticalAlignment="Top" HorizontalAlignment="Left" Grid.Column="5"/>
</Grid>
</WrapPanel>
This works fine too even with the other auto sized columns. The key seems to be the wrappanel and the one * sized column. If you set them all to auto it doesn't work.
I hope this and Quartermeister's answer helps somebody, because this drove me #$%#$% crazy.
The below code will result in the following output, is that what you are looking for???
longer keeps going and going... [red rectangle]
<Grid Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="longer keeps going and going testgrand you going and then t" TextTrimming="CharacterEllipsis"/>
<Rectangle Grid.Column="1" Fill="#FFDE3030" Stroke="Black" VerticalAlignment="Top" Height="41" Width="41" />
</Grid>
I had a somewhat similar problem; I wanted to show some content with an externally-sized border area but containing two TextBlocks, where the first is auto-sized and the second is fixed-sized, and the second floats left as the first gets smaller but stops at the right edge (so the first block's text is clipped instead of the second becoming invisible).
Distilling the previous answers, it appears that the key bit of magic is simply to use HorizontalAlignment="Left" with the first column set to star-sized.
<Border BorderThickness="1" BorderBrush="Black">
<Grid HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Value}" />
<TextBlock Grid.Column="1" Text="⏫" Margin="4,0,0,0" Foreground="Blue" />
</Grid>
</Border>
It appears that the way this works is that (a bit counter-intuitively) the Border stays full width (as set by its parent layout), while the Grid will size to its content -- except that it will not get wider than the containing Border. This keeps the second TextBlock visible.