How to change control alignment depending on available space? - c#

Imagine this. I've got a Border which contains some custom wpf control, lets call it MyControl. This Border stretches itself when window is resized (to fill available space). MyControl size is fixed. Now, I want my control to have HorizontalAlignment="Center" when it fits the available space, and HorizontalAlignment="Left" when it doesn't. I'm having trouble figuring out how to implement such behaviour though.
I guess, i can subscribe to Border's SizeChanged event and change alignment in code-behind depending on ActualWidths of Border and MyControl, but isn't there an easier way? Can this be achieved by databinding or by attached behaviour?

It will automatically behave like that if you set the control's Width and Height to fixed values and HorizontalAlignment and VerticalAlignment to Stretch instead of Center:
<Border BorderBrush="Red" BorderThickness="5">
<my:MyControl Width="200" Height="150"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Border>

Related

WPF Calculated FontSize Inside ViewBox

I have faced a problem and tried the internet and threads here to find a solution but haven't found yet.
I am a beginner in programming any help will be appreciated.
I have a window which will be displayed on the secondary screen and a TextBlock wrapped in a viewbox and the text is binded and will be populated dymnamically on runtime on the second screen. The fontsize is also Binded and can be changed by the user.
This is working perfectly well.
The Problem Is That when the user increases fontsize to a higher value the text looks good if the text is short but if the text is very very large the text looks ugly sometimes becomes unreadable.
I have tried the ViewBox's Sretch direction and stretch but haven't found a better way to solve my problem but manually if there is very very long text and the text is unreadable reducing the fontsize makes text readable.
How may i be helped. One solution I have in mind is to calculate the fontsize maybe on height and width of parent grid such that when the text is very long the calculation reduces the fontsize to where it becomes readable.
here is my sample Xaml
<Grid>
<Viewbox Stretch="Fill"
StretchDirection="DownOnly">
<TextBlock Text="{Binding}"
Width="{Binding}"
FontSize="{Binding}"
TextWrapping="Wrap">
</TextBlock>
</Viewbox>
</Grid>
Here is the Ugly Behavior when text is very long and fontsize is set highly
Expected behavior. Here the fontsize is manually set lower
Okay I found a work around the problem. If anyone has another solution it will be welcomed.
I wrapped the textblock inside a border and removed binding of the width of the textblock and I will be increasing and decreasing the width. If font size increases I will decrease the width by a ratio in the ViewModel and vice versa.
<Grid>
<Viewbox >
<Border>
<TextBlock Text="{Binding}"
Width="{Binding}"
FontSize="{Binding}"
TextWrapping="Wrap">
</TextBlock>
</Border>
</Viewbox>

Canvas improperly overlaying a TextBlock component inside a DockPanel

In the image here, each block with a number in it represents a laser. These blocks are laid out on a canvas inside a DockPanel. Also inside the DockPanel docked to the top is the red TextBlock that you can see is hiding behind the laser map canvas. Why is this happening? The TextBlock is docked to the top of the DockPanel and canvas has no dock setting, therefore it should fill the rest of space. Also of note: I had to put the DockPanel inside a ViewBox in order for the whole center screen space to scale properly on window resizes. Then I had to put that ViewBox inside a ScrollViewer to allow scroll bars to appear when needed.
Here is the XAML Code for the center screen (Note: Child of the Window is a DockPanel. Menu is docked to the top, left-hand button panel is docked to the left, right-hand button panel is docked to the right, the status bar is docked to the bottom and everything you see in the center screen is defined by the following XAML code)
<ScrollViewer
Name="centerScreenScrollViewer"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="{Binding IsScrollbarsVisible, Converter={StaticResource BoolToScrollbarVisConverter}, FallbackValue=Hidden}">
<Viewbox>
<DockPanel
LastChildFill="True">
<TextBlock
DockPanel.Dock="Top"
Name="tbkFullVisual"
Style="{StaticResource tbkStyleBlue}"
Foreground="Red"
IsEnabled="{Binding FullVisual}"
HorizontalAlignment="Center"
VerticalAlignment="Top"
FontSize="24">
*** This Print Requires Full Visual Inspection! ***
</TextBlock>
<Canvas x:Name="mapCanvas">
<ContentPresenter Content="{Binding MapCanvas}"/>
</Canvas>
</DockPanel>
</Viewbox>
</ScrollViewer>
Any help in solving this issue will be greatly appreciated.
Regards,
Kyle
This has to do with the way that a ViewBox works, in particular with the Canvas element. The ViewBox is used to resize child elements, as I'm sure you're aware. There are 2 issues with the Canvas element:
The default Height and Width are 0, which means that the TextBlock will get all the space.
The Canvas element lets you draw outside of its own boundaries, so even if your canvas is tiny or not even visible, you would be allowed to render your grid of numbers.
The quickest solution is to set VerticalAlignment on the ViewBox:
<Viewbox VerticalAlignment="Top">
...
</Viewbox>
You could set a Height on the Canvas, but I think this is less ideal because you don't want to change this dynamically with window resize.

scrollviewer with the textbox

I have a textbox which is contained in a scrollviewer as below:
<ScrollViewer x:Name="myScrollViewer" Height="200" Width="500" HorizontalAlignment="Left">
<TextBox x:Name="myTextBox" Width="500" TextWrapping="Wrap"/>
</ScrollViewer>
When I input a large number of data in the textbox, the scrollviewer will not scroll down automatically, so this lead I couldn't see what I'm inputing now in the textbox, I have to scroll down manully and see the content which I am inputting. I have two questions:
How to let the scrollbar automatically scroll down follow the line which I am writing now.
TextBox has a border, but if I scroll down, the top border will disappear, it looks like the text box is scroll up, how to make the textbox not changes, the 4 borders always appear and only the content wrapped?
Do you need to use a ScrollViewer, or can you use the TextBox's own scrolling behaviour?
This behaves as you would want in normal Silverlight apps (can't test it on a windows 8 app right atm)
E.G.
<TextBox
Height="200"
Width="500"
TextWrapping="Wrap"
AcceptsReturn="True"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"/>
(Note that you don't seem to be able to set the HorizontalScrollBarVisibility and VerticalScrollBarVisibility properties from a Style)

How to define stroke around background rectangle of textblock in WPF?

I would like to have some text to be inside a rectangle with stroke around this rectangle (just like property "Stroke" of the object "Rectangle" itself). But I didn't manage to find a property of the object "Textblock" which defines such a stroke.
You can place the TextBlock inside a Border and set the properties of the Border to draw the rectangle around your text.
Every TextBlock element contains one or more child Inline elements. There is a type of Inline (InlineUIContainer) that supports hosting a UIElement: basically, this means you can host arbitrary UI elements within a TextBlock. Flipping #GraemeF's answer on its head, you can host a Border element inside the TextBlock, like so:
<Window x:Class="StackOverflowWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TextBlock FontSize="24" Padding="20">
<Run>Hello</Run>
<InlineUIContainer>
<Border BorderBrush="Black" BorderThickness="1" Padding="4" Margin="0,0,0,-11">
<TextBlock Text="Boxed" />
</Border>
</InlineUIContainer>
<Run>World</Run>
</TextBlock>
</Window>
This will look something like this:
You will have to experiment with the Margin on the Border element in order to get the text baselines to match up, but other than that the technique seems to work well.

Aligning content in a WPF Viewbox

I have a Viewbox with Stretch=Uniform in order to not distort the content.
However, when the frame window is wider or taller than the content, the Viewbox content is always centered.
I cannot seem to find any content alignment options on the Viewbox.
Is there a way to do this?
Try VerticalAlignment="Top" and HorizontalAlignment="Left" on your viewbox. It will cause it to be anchored to the top and left side.
<Grid>
<Viewbox VerticalAlignment="Top" HorizontalAlignment="Left">
...
</Viewbox>
</Grid>
If you want it to completely fill (but keep it uniform) you can use Stretch="UniformToFill"
According to MSDN the Viewbox is used to stretch the child elements. Since the child elements would be stretched, you would have to set the content alignment of the children.
You may want to look at this for more information on the Viewbox: How do I keep aspect ratio on scalable, scrollable content in WPF?

Categories

Resources