I have a TextBlock within a ScrollViewer that aligns with stretch to its window. I need the TextBlock to behave as the following:
Resizes with window, no scrollbars
When resized below a certain width the TextBlock needs to keep a MinWidth and scrollbars should appear
TextWrapping or TextTrimming should work appropriately
How can I get this functionality?
I have tried several ways, involving bindings to ActualWidth & ActualHeight, but can't get it to work.
This can't be that difficult, what am I missing?
Here is a code sample to put in XamlPad (no MinWidth is set yet):
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<TextBlock TextWrapping="Wrap" Text="Some really long text that should probably wordwrap when you resize the window." />
</ScrollViewer>
</Window>
This works:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
Name="Scroller">
<TextBlock HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
MinWidth="100"
Width="{Binding ElementName=Scroller, Path=ViewportWidth}"
TextWrapping="Wrap"
Text="Some really long text that should probably wordwrap when you resize the window." />
</ScrollViewer>
</Window>
Without more detail, the best I can do is provide the standard way of doing this. Basically, host your element (which has a minimum size) in a scroll viewer; when the scrollviewer is resized small enough such that the element cannot wholly fit inside it, it will automatically display scroll bars. Example:
<ScrollViewer>
<Button MinWidth="100" MinHeight="50"/>
</ScrollViewer>
Related
The issue: Cannot get the Vertical Scroll bar for the DataGrid to appear unless I set a static height on the grid. I know similar questions have been asked before, however unlike other questions my example is a lot more simple with no Grid Columns. The DataGrid is simply inside a StackPanel inside the control. That's it, and no combination of Auto, "*", etc works except setting a static Height.
Is this simply a lacking feature in WPF framework that it a Observable Collection on the ViewModel bound to a grid, will not notify the View when items are added to the VM Collection? Do I have to code a custom property and bind the DataGrid Height to that?
Here is my XMAL:
<Window x:Class="Monster.Configure"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:Monster.ViewModels"
xmlns:local="clr-namespace:Monster"
mc:Ignorable="d"
Title="Configure" Width="1200">
<Window.DataContext>
<viewModels:ViewModelMain/>
</Window.DataContext>
<Window.Resources>
<BooleanToVisibilityConverter x:Key="b2v" />
</Window.Resources>
<Grid>
<StackPanel Margin="5">
<Button Name="button_Refresh" Content="Save / Refresh" HorizontalAlignment="Left" Margin="5" Width="100"
Click="button_Refresh_Click"></Button>
<StackPanel Orientation="Horizontal">
<!--Buttons and other junk here-->
</StackPanel>
<Label></Label>
<DataGrid Name="dataGrid_PendingCreation" CanUserAddRows="True" CanUserDeleteRows="True" AutoGenerateColumns="False"
ItemsSource="{Binding URLsForGrid}"
Loaded="dataGrid_PendingCreation_Loaded"
CellEditEnding="dataGrid_PendingCreation_CellEditEnding"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility ="Auto"
Width="Auto" Height="Auto">
<DataGrid.Columns>
<!--Columns and junk here-->
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</Grid>
</Window>
As you can see, the user is allowed to add new rows. When doing so, a Vertical Scroll Bar never shows up unless a Static Height is set in the DataGrid.
Your DataGrid is wrapped inside a StackPanel (with vertical orientation). A vertically oriented StackPanel always gives seemingly infinite available height to its children. Since your DataGrid's Height property is set to Auto, it will grow as large as it can; it will never show a vertical scrollbar, because this is done only if the DataGrid's available height (determined by the parent) is less than the actually needed height.
The solution is not to use a StackPanel here. Instead, use a Grid or a DockPanel.
I usually prefer the latter, if all I want to achieve is vertical or horizontal stacking of the children and have one child stretch as wide as possible; here is how it would be done:
<Window>
...
<Grid>
...
<DockPanel Margin="5">
<Button DockPanel.Dock="Top" Name="button_Refresh" ... />
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<!--Buttons and other junk here-->
</StackPanel>
<Label DockPanel.Dock="Top"></Label>
<DataGrid Name="dataGrid_PendingCreation" ... />
</DockPanel>
...
</Grid>
...
</Window>
Make sure that DataGrid is the last child in the DockPanel and that it has no DockPanel.Dock property. This ensures that the DataGrid will be given the available height and width that remains after placing all other controls.
I'm quite new in C# WPF. I want my Popup control to be positioned in a certain coordinates of the user's screen. and I want to make my textblock text center in the textblock itself. I tried to add a block but it doesn't work. Look at my XAML codes: (I'm 97% done in my personal project. :) )
Also, look at my screenshot, I put a red box there, I want my popup control to be there, although it is not my priority cause the original position is quite fine with me, but I would be glad if this will be moved.
Next, look at the annoying text, it is not centered.
The current position of the popup is in the left most and upper most part of my screen.
<Window x:Class="KeyLocks_Notifier.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Popup Name="Popup1" AllowsTransparency="True" PlacementRectangle="0,0,30,50" Placement="Center"
PopupAnimation="Fade">
<Border BorderBrush="{x:Null}" Height="50">
<TextBlock Name="myPopupText"
Background="#FF9700FF"
Height = "40"
Width="180"
Foreground="White" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Effect>
<DropShadowEffect/>
</TextBlock.Effect>
</TextBlock>
</Border>
</Popup>
</Grid>
</Window>
On the window :
In XAML there is a WindowStartupLocation on the root level with 3 options (Manual, CenterScreen, CenterOwner)
If you want a custom Location on your screen you need to set WindowStartupLocation to Manual and set the Top & Left with pixel
For your popup :
You can set the Placement to custom
Example Here
And for your text position Here
Alright, so I have a XAML page with a TextBlock in a Windows Phone 8 application. My dilemma is this:
I pragmatically add more content (formatted lines with Inlines.Add(new Run...) to the TextBlock. The text block is currently filled from bottom to up because of the ScrollViewer in the sense that a line appears in the bottom after another. I would also be fine with them starting to appear from the top as long as the TextBlock would continue to scroll down (actually this might look better) once it is full. My TextBlock is inside a ScrollViewer as below:
<Popup x:Name="send_message_xaml" Grid.Row="1" VerticalOffset="0" Width="750" Height="auto">
<StackPanel Orientation="Vertical" Margin="0,0" Width="auto" Height="auto">
<ScrollViewer Height="345" HorizontalAlignment="Left" Margin="0,0,0,0" Name="scrollViewer1" VerticalAlignment="Bottom" Width="420" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="message_log" Margin="40,50,0,0" TextWrapping="Wrap" Width="420" VerticalAlignment="Top" FontSize="22"/>
</ScrollViewer>
<TextBox x:Name="message_to_send" InputScope="Chat" Width="480" KeyDown="message_to_send_KeyDown" Margin="15,0"/>
</StackPanel>
</Popup>
How can I get the textblock to scroll so that the newest appended message is always at the bottom? I found a bunch of these threads but none seem to solve my problem so far. Do I need to add some code somewhere with the appending?
You need to update the VerticalOffset based on the ScrollableHeight. When you add new inlines to the TextBlock, its height is going to change and that will notify the parent ScrollViewer. So, after you add new items to the inlines, run the Measure method and update the VerticalOffset.
Here is an example.
So I posted this question but the suggested answers do not seem to work. So once again, re-posting it, much simpler version of the XAML. We usually expect the TextBox to resize as the Window resize. I want the "other-way-around" behavior. TextBox that takes the whole Window area. The TextBox grows/shrinks in size, the Window follows. Please suggest on ways doing it.
<Window>
<Grid HorizontalAlignment="Stretch">
<TextBox Width="Auto">
</TextBox>
</Grid>
</Window>
<Window x:Class="MiscSamples.SizeToContent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SizeToContent" SizeToContent="WidthAndHeight" ResizeMode="NoResize">
<Grid HorizontalAlignment="Stretch">
<TextBox Width="Auto" AcceptsReturn="True">
</TextBox>
</Grid>
</Window>
Notice that you have to include ResizeMode="NoResize", because if the user resizes the window manually, the behavior is lost.
You could give the textbox a name and then bind the window width to the size of the textbox as such:
<Window Width="{Binding ElementName=txtbox, Path=ActualWidth}">
<Grid HorizontalAlignment="Stretch">
<TextBox x:Name="txtbox" Width="Auto">
</TextBox>
</Grid>
</Window>
I've not included any code for sizing the textbox (I assume you're going to do that programmatically or so) but with this XAML the window should size to the textbox width.
I've got a grid with several TextBoxes in it. I want to keep this grid fixed at the bottom of my main window. So if the user scrolls down the grid should basically stay in it's place.
One way I thought of doing this was to get some sort of value from the ScrollViewer and add it to the grids Canvas.TopProperty. However I am not sure which value changes when the user scrolls up or down.
Then don't put the scroll on the main window. Put ScrollViewer only on the content (rows) that you want to scroll. Careful not to use an auto for the height of the rows with the ScrollViewer or the container will grow to support all the content and the Scroll does not come into play.
One way:
<Window x:Class="Sample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<ListBox>
<!--Hardcoded listbox items just to force the scrollbar for demonstration purposes -->
<ListBoxItem>Item1</ListBoxItem>
<ListBoxItem>Item2</ListBoxItem>
<ListBoxItem>Item3</ListBoxItem>
<ListBoxItem>Item4</ListBoxItem>
<ListBoxItem>Item5</ListBoxItem>
<ListBoxItem>Item6</ListBoxItem>
<ListBoxItem>Item7</ListBoxItem>
<ListBoxItem>Item8</ListBoxItem>
<ListBoxItem>Item9</ListBoxItem>
<ListBoxItem>Item10</ListBoxItem>
<ListBoxItem>Item11</ListBoxItem>
<ListBoxItem>Item12</ListBoxItem>
<ListBoxItem>Item14</ListBoxItem>
<ListBoxItem>Item15</ListBoxItem>
<ListBoxItem>Item16</ListBoxItem>
<ListBoxItem>Item17</ListBoxItem>
<ListBoxItem>Item18</ListBoxItem>
<ListBoxItem>Item19</ListBoxItem>
<ListBoxItem>Item20</ListBoxItem>
<ListBoxItem>Item21</ListBoxItem>
<ListBoxItem>Item22</ListBoxItem>
</ListBox>
<Grid Panel.ZIndex="5" VerticalAlignment="Bottom" Background="DarkGray">
<StackPanel>
<TextBox HorizontalAlignment="Left" VerticalAlignment="Center">Text box 1</TextBox>
<TextBox HorizontalAlignment="Left" VerticalAlignment="Center">Text box 2</TextBox>
<TextBox HorizontalAlignment="Left" VerticalAlignment="Center">Text box 3</TextBox>
</StackPanel>
</Grid>
</Grid>