Display dynamic width of container in WPF - wpf

<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="0.55*" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Background="Gray">
<TextBlock x:Name="EmployeeNameTextBlock"
VerticalAlignment="Center"
Margin="50,0,0,0"
FontSize="18"
RenderTransformOrigin="0.5,0.5"
Text="Content09asdfadsdsdasdfasd92168132 "
TextWrapping="NoWrap"
/>
<ToggleButton x:Name="btn"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Center"
Height="30"
Width="30" >
Button
</ToggleButton>
</StackPanel>
<Label Grid.Column="1" Background="Yellow" />
</Grid>
This is my code i have issue in displaying the toggle button, you can refer to screen shot below for currently displaying and expectation
conditions
* button should be always end of the text block even content is small or big
* if content is bigger then container, textbox size should stop at before less width of button. so that we can see toggle button on display. as shown in expected screen shot.
Result Screenshot long text
Result Screenshot small text
Expected screenshot long text
Expected Screenshot small text
Please any one help on this
Thanks in advance
Solution
<Grid SizeChanged="Grid_SizeChanged">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="0.55*" />
</Grid.ColumnDefinitions>
<Border Name="rightBlk" Background="Green" Grid.Column="1" />
<Grid VerticalAlignment="Center" Background="Gray">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="EmployeeNameTextBlock"
VerticalAlignment="Center"
Margin="50,0,0,0"
TextTrimming="CharacterEllipsis"
FontSize="18"
RenderTransformOrigin="0.5,0.5"
Text="Content09asasdfasdfd "
TextWrapping="NoWrap"
Padding="0,0,30,0"
/>
<ToggleButton x:Name="btn"
HorizontalAlignment="Right"
Margin="0,0,0,0"
VerticalAlignment="Center"
Height="30"
Width="30" >
Button
</ToggleButton>
</Grid>
<Label Grid.Column="1" Background="Yellow" />
</Grid>
Code Behide
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
EmployeeNameTextBlock.MaxWidth = ((Grid)sender).ActualWidth - 50 - rightBlk.ActualWidth;
}
Thank you #lvan and #Neptune for helping me to solve this issue.

You can replace the StackPanel with a Grid. This way you have more control on distribution and can give your Button priority to get its width first before allocating the remaining to the TextBlock:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="0.55*" />
</Grid.ColumnDefinitions>
<Grid VerticalAlignment="Center" Background="Gray">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="EmployeeNameTextBlock"
VerticalAlignment="Center"
Margin="50,0,0,0"
TextTrimming="CharacterEllipsis"
FontSize="18"
RenderTransformOrigin="0.5,0.5"
Text="Content09asdfadsdsdasdfasd92168132 "
TextWrapping="NoWrap"
/>
<ToggleButton x:Name="btn" Grid.Column="1"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Center"
Height="30"
Width="30" >
Button
</ToggleButton>
</Grid>
<Label Grid.Column="1" Background="Yellow" />
</Grid>
I added an attribute TextTrimming if you want to indicate to user there's missing text but you can remove it if that's not needed.
The code above produces this result when the width is limited:

You can get what you are looking for with either you code and adding
MaxWidth="270" and TextTrimming="CharacterEllipsis" to textbox
or Neptunes code and changing
<ColumnDefinition Width="*" /> to "Auto" and also adding MaxWidth="270" to textbox.
I don't think you can do it without setting a MaxWidth on the textbox but that means you'll have to recalculate it if you resize your window.
To recalculate:
Subscribe to main window size changed event:
SizeChanged += MainWindow_SizeChanged; within main window constructor or in xaml
And add to codebehind:
private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
EmployeeNameTextBlock.MaxWidth = StackPanelName.ActualWidth - btn.ActualWidth;
}
You might need to use .Width instead of Actual width, and you can also try using the column instead of the stack panel but this illustrates the recalculation you need to do.

Related

WPF – How to set shortcut for custom button (image and TextBlock)

I Have a little WPF window that contains 3 buttons with image and TextBlock like this :
<Button x:Name="cmdPrint" Margin="5" VerticalAlignment="Center" Grid.Column="2"
ToolTip="Print a simulation"
MouseMove="MouseMouveHandler"
Click="ButtonClickHandler" Height="36">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="70"/>
</Grid.ColumnDefinitions>
<Image Source="images\print.png" Grid.Column="0" VerticalAlignment="Center"
Margin="2"/>
<TextBlock Text="_Print" Grid.Column="1" Foreground="DarkBlue"
VerticalAlignment="Center" Margin="2"/>
</Grid>
</Button>
As you can see , the button is customized, so, the following code doesn’t work :
<Button Name="cmdPrint " Content="_Print"></Button>
Is it possible to Fire Print button when i Press ‘P’ key ?
Thank you in advance.
Use label instead of text block will work for you
Click="ButtonClickHandler" Height="36" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="70"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" VerticalAlignment="Center"
Margin="2"/>
<Label Content="_Print" Grid.Column="1" Foreground="DarkBlue"
VerticalAlignment="Center" Margin="2" />
</Grid>
</Button>

How to cut TextBox width to prevent out of the Grid?

I have the next layout
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Grid.Row="0" Grid.RowSpan="2" Grid.Column="0" Width="60" Height="60" />
<StackPanel Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Orientation="Horizontal">
<TextBlock Text="Title should be long" HorizontalAlignment="Left" />
<Ellipse Fill="White" Stroke="White" Width="7" Height="7" />
</StackPanel>
<TextBlock Grid.Row="1" Grid.Column="1" Text="Message" />
<TextBlock Grid.Row="1" Grid.Column="2" Text="Info" />
</Grid>
I have an issue in the StackPanel which hosts a Title and Ellipse, the goal is the Online marker by the ellipse whitch should be placed at the end off the title. But it shouldn't out of a view part.
I have tried to put TextBox and Ellipse into cells of the Grid unfortunatly it doesn't help.
<Grid Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2">
<Grid.ColumnsDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnsDefinitions>
<TextBlock Grid.Column="0" Text="Title should be long" HorizontalAlignment="Left" />
<Ellipse Grid.Column="1" Fill="White" Stroke="White" Width="7" Height="7" />
</Grid>
In my mind it should render correct, but the ellipse is out of view port again.
This is a Expression Blend layout scrinshots, the same layout is rendering in runtime.
The Grid bounds:
The TextBox bounds:
The Ellipse bounds:
So the TextBox and Ellipse is out of the grid :(
Update: I need the next behaviour of layout
1) Short title, the ellipse attached to the title end
2) Long title, the ellipse attached to the right side of container
I tried your code and it renders fine (in other terms it renders in the viewport. See red arrow). Please find attached a screenshot of the results. (I added the showgridlines just to illustrates the rows and cols)
//--- Changed testing and fixed code for intended effect ---//
Code changes in XAML: Swapped the width values for the columndefinitions. Added Textwrapping to textblock in order to see entire text. (You could opt for texttrimming instead depending on your aesthetics.)
<Grid Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Title should be really really really really really long" HorizontalAlignment="Left" TextWrapping="Wrap" />
<Ellipse Grid.Column="1" Fill="White" Stroke="White" Width="7" Height="7"/>
</Grid>
Outcome:

DockPanel LastChildFill resizing to MinWidth?

I try to achieve a simple menubar in WPF.
Here is the XAML:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DockPanel>
<DockPanel Background="Black" VerticalAlignment="Top" LastChildFill="True" DockPanel.Dock="Top" Height="28">
<ToggleButton Content="--" Visibility="Collapsed" />
<StackPanel Orientation="Horizontal">
<Button Content="Add" />
<Button Content="Expand" />
</StackPanel>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<TextBox Text="Search" MinWidth="80" Width="200" />
<Button Content="X" Margin="0,1,50,0" />
</StackPanel>
</DockPanel>
</DockPanel>
</Page>
It looks good, but when I resize the page to a smaller width, the last child (the Stackpanel with the search textbox) is hiding behind the left items.
Like this:
http://s9.postimage.org/m0tkrobwd/printscreen.png
It would be good if the textbox would resize itself if it has enough space to achieve its MinWidth...Is it possible?
The tricky thing is to give a Control (in your case the SearchTextBox) an alignment but still catch the available space up to MaxWidth. Thanks to this answer.
<DockPanel>
<DockPanel Background="Black" DockPanel.Dock="Top" Height="28">
<ToggleButton DockPanel.Dock="Left" Content="--" Visibility="Collapsed" />
<StackPanel DockPanel.Dock="Left" Orientation="Horizontal">
<Button Content="Add" />
<Button Content="Expand" />
</StackPanel>
<Button DockPanel.Dock="Right" Content="X" />
<Border Name="Container">
<TextBox Text="Search" HorizontalAlignment="Right"
Width="{Binding ElementName=Container, Path=ActualWidth}" MaxWidth="200" />
</Border>
</DockPanel>
</DockPanel>
Container could be another Control too.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition MaxWidth="200" MinWidth="80"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ToggleButton Content="--" Visibility="Collapsed" />
<Button Content="Add" Grid.Column="1"/>
<Button Content="Expand" Grid.Column="2"/>
<TextBox Text="Search" Grid.Column="4"/>
<Button Content="X" Margin="0,1,50,0" Grid.Column="5" />
</Grid>
Instead of giving MaxWidth and MinWidth to TextBox give it to Grid Column.I hope this will help.
Hi Set MaxWidth and MinWidth for the TextBox Not Width. If you will set the Width then it has highest precedence and hence MinWidth won'nt come into act.I hope this will help.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ToggleButton Content="--" Visibility="Collapsed" />
<Button Content="Add" Grid.Column="1"/>
<Button Content="Expand" Grid.Column="2"/>
<TextBox Text="Search" MinWidth="80" MaxWidth="600" Grid.Column="3" ClipToBounds="True" />
<Button Content="X" Margin="0,1,50,0" Grid.Column="4"/>
</Grid>
Its just because of the size of page is not enough for showing both stackpanel on page. for this you can use the minimum size of the page. that will prevent the damages of the control hiding .
and its also up to you what design you want. you can either use grid rather then stackpanles.

WPF: Aligning GRID contents with respect to a bitmap

I have to display few strings under a bitmap . At a time maximum number of strings that can displayed are 5 and not always all the 5 strings will be displayed. Also the length of the strings vary. Whatever be the case, I want to display these strings in a visually appealing manner under the bitmap. Like, if just one string, I want to position it centrally under the bitmap. If 2 strings, I want to space the strings nicely and center it under the bitmap and so.
I know only at run time the strings to display, number of strings ( min 1 and max 5) to display and also length of string.
I wrote the below XAML code, but I am unable to position the strings nicely for all my conditions. Bitmap1 is a circle, bitmap2 is left arrow and bitmap3 is right arrow.
Can someone help me here?
<Grid x:Name="Graphics" Grid.Column="1" Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="0.319*"/>
<RowDefinition Height="0.56*"/>
<RowDefinition Height="0.321*"/>
</Grid.RowDefinitions>
<Image Height="72" Source="/DataBinding;component/Bitmap1.bmp" Stretch="Fill" Width="108" Grid.Row="1" />
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.408*"/>
<ColumnDefinition Width="0.15*"/>
<ColumnDefinition Width="0.408*"/>
</Grid.ColumnDefinitions>
<Image x:Name="Next" Height="48" Width="48" Grid.Column="2" Source="/DataBinding;component/Bitmap3.bmp" HorizontalAlignment="Left" />
<Image x:Name="Prev" Width="48" Height="48" Grid.Column="0" Source="/DataBinding;component/Bitmap2.bmp" HorizontalAlignment="Right"/>
<Grid HorizontalAlignment="Center" ShowGridLines="True" Width="Auto" Grid.ColumnSpan="3" Margin="38,69,41,-40">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Visibility="Visible" Text="String1" Padding="10" Grid.Column="0" FontSize="14.667" TextAlignment="Center" Foreground="White" />
<TextBlock Visibility="Visible" Text="String2" Padding="10" Grid.Column="1" FontSize="14.667" TextAlignment="Center" Foreground="White" />
<TextBlock Visibility="Visible" Text="String3" Padding="10" Grid.Column="2" FontSize="14.667" TextAlignment="Center" Foreground="White" />
<TextBlock Visibility="Visible" Text="String4" Padding="10" Grid.Column="3" FontSize="14.667" TextAlignment="Center" Foreground="White" />
<TextBlock Visibility="Visible" Text="String5" Padding="10" Grid.Column="4" FontSize="14.667" TextAlignment="Center" Foreground="White" />
</Grid>
</Grid>
</Grid>
What you want to do is create a custom panel by creating a custom control based on panel. Override ArrangeOverride and then place things exactly where you want them as if you have a canvas to work with, because your panel is like a canvas when you override ArrangeOverride. Grids are a custom panel themselves :-)
<StackPanel Name="stack1" Orientation="Horizontal" Width="Auto" Background="Red" >
<TextBlock FontSize="14.667" Width="Auto" TextAlignment="Center">
<Run x:Name="String1" Text="String1" />
<Run x:Name="String2" Text="String2" />
<Run x:Name="String3" Text="String3" />
<Run x:Name="String4" Text="String4" />
<Run x:Name="String5" Text="String5" />
</TextBlock>
</StackPanel>
</Grid>
</Grid>

WPF layout for autosize textblock and icon floating on the right - how?

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.

Resources