如何将任何 UI 元素放置在被修剪的文本末尾

How to place any UI element at the end of text that is trimmed

我有一个包含 TextBlock 和 Ellipse 的自定义控件。 我想将此 Ellipse 放置在 TextBlock 结束的位置。如果缺少 space 文本应该被修剪并且椭圆应该保留在它的位置。我创建了非常简单的示例来说明问题。

MainPage.xaml.cs:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" x:Name="MainGrid" HorizontalAlignment="Stretch">

    <Grid Height="50">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <local:TextWithEllipse x:Name="Control1" Grid.Row="0"/>
        <local:TextWithEllipse x:Name="Control2" Grid.Row="1"/>
    </Grid>
</Grid>

MainPage.cs:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        SizeChanged += OnSizeChanged;
        Loaded += OnLoaded;
    }

    private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
    {
        Control1.Text = "One two three four five six seven eight nine ten One two three four five six seven eight nine ten";
        Control2.Text = "Short text";
    }

    private void OnSizeChanged(object sender, SizeChangedEventArgs e)
    {
        Control1.Width = e.NewSize.Width;
        Control2.Width = e.NewSize.Width;
    }
}

完成了什么:TextWithEllipse 控件的宽度与应用程序 window 的宽度相同,并且向它们写入了一些文本 - 短文本和长文本。

此控件如下所示:

TextWithEllipse.xaml.cs:

<UserControl
x:Class="TextResize.TextWithEllipse"
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"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">

<Grid Height="20" HorizontalAlignment="Stretch" Background="MediumPurple">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="20" MinWidth="20"/>
    </Grid.ColumnDefinitions>

    <TextBlock Grid.Column="0" HorizontalAlignment="Stretch" x:Name="TestTitle"
               TextTrimming="CharacterEllipsis" FontSize="16"/>

    <Ellipse Width="20" Height="20" Fill="Red" Grid.Column="1" HorizontalAlignment="Left"/>

</Grid>

TextWithEllipse.cs:

public sealed partial class TextWithEllipse : UserControl
{
    public TextWithEllipse()
    {
        InitializeComponent();
    }

    public string Text
    {
        get { return TestTitle.Text; }
        set { TestTitle.Text = value; }
    }
}

如果文本宽度小于控件宽度,它工作正常。如果文本很长并且需要更多 space,它会超出 window,除非您扩展 windows 宽度,否则不会显示椭圆。 当第一个 Column width 更改为 '*' 时:

<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20" MinWidth="20"/>

情况是当文本比 window 宽度更大时,文本正在被修剪并且 Ellipse 在正确的位置。但是如果文字很短,Ellipse不会放在正文之后,而是放在window.

的末尾

我怎样才能做到这一点?

您可以尝试使用 RelativePanel:

<RelativePanel HorizontalAlignment="Stretch" Height="20">
    <TextBlock HorizontalAlignment="Stretch" x:Name="TestTitle" TextTrimming="CharacterEllipsis" FontSize="16" Padding="0,0,20,0"/>
    <Ellipse Width="20" Height="20" Fill="Red" RelativePanel.AlignRightWith="TestTitle"/>
</RelativePanel>

您也不需要在 OnSizeChanged 中更改宽度 - 即使没有此事件它也会自动更改。

我仔细研究了您的代码以找到解决方案。正如您发现设置 ColumnDefinition Width="Auto" 不起作用,因为它告诉 TextBlock 它拥有所需的 space,因此它永远不会 trim。所以设置ColumnDefinition Width="*"是正确的做法,但是作为一个小细节,把整个GridHorizontalAlignment属性改成Left,因为这样整个Grid 只会在需要时拉伸(当您有很多文本时会发生这种情况)。整个代码将是:

<Grid Height="20" HorizontalAlignment="Left" Background="MediumPurple">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="20" MinWidth="20"/>
    </Grid.ColumnDefinitions>

    <TextBlock Grid.Column="0" HorizontalAlignment="Stretch" x:Name="TestTitle"
           TextTrimming="CharacterEllipsis" FontSize="16"/>

    <Ellipse Width="20" Height="20" Fill="Red" Grid.Column="1" HorizontalAlignment="Left"/>

</Grid>

这至少在 XAML Designer 中为我提供了您想要的行为。