TextTrimming слева - программирование
Подтвердить что ты не робот

TextTrimming слева

Есть ли способ указать обрезку текста на TextBlock с левой стороны?

Мне удалось выполнить два из трех сценариев (третий - тот, который мне нужен):

  • Регулярная обрезка

    <TextBlock 
        VerticalAlignment="Center" 
        Width="80" 
        TextTrimming="WordEllipsis"
        Text="A very long text that requires trimming" />
    
    // Result: "A very long te..."
    
  • Левая обрезка

    <TextBlock 
        VerticalAlignment="Center" 
        Width="80" 
        FlowDirection="RightToLeft"
        TextTrimming="WordEllipsis"
        Text="A very long text that requires trimming." />
    
    // Result: "...A very long te"
    
  • Левая обрезка, где отображается конец текста

    // Desired result: "...uires trimming"
    

Кто-нибудь знает, возможно ли это? Благодарю.

4b9b3361

Ответ 1

Вы не можете делать это из коробки, но я могу думать о двух вещах, которые могут сработать:

1) Создайте вложенное свойство TextBlock, которое называется нечто вроде LeftTrimmingText. Затем вы должны установить это свойство вместо свойства Text. Например.

  <TextBlock my:TextBlockHelper.LeftTrimmingText="A very long text that requires trimming." />

Вложенное свойство подсчитывает, сколько символов действительно может отображаться, а затем соответствующим образом задайте свойство Text для TextBlock.

2) Создайте свой собственный класс, который обертывает TextBlock, и добавьте ваши собственные свойства, чтобы позаботиться о требуемой логике.

Я думаю, что первый вариант проще.

Ответ 2

Если вам не нужны эллипсы, но просто хотите увидеть конец текста вместо начала, когда он отключится, вы можете обернуть TextBlock внутри другого контейнера и установить его HorizontalAlignment вправо. Это отключит его так, как вы хотите, но без elipse.

<Grid>
    <TextBlock Text="Really long text to cutoff." HorizontalAlignment="Right"/>
</Grid>

Ответ 3

Этот стиль выполнит эту работу. Трюк состоит в том, чтобы переопределить шаблон управления для метки. Затем содержимое помещается внутри холста для обрезки и выравнивается справа от холста. Минимальная ширина содержимого - это ширина холста, поэтому текст содержимого будет выровнен по левому краю, если при обрезании будет достаточно места и выровнено по правому краю.

Эллипсы включаются, если ширина содержимого больше холста.

<Style x:Key="LeftEllipsesLabelStyle"
       TargetType="{x:Type Label}">
    <Setter Property="Foreground"
            Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
    <Setter Property="Background"
            Value="Transparent" />
    <Setter Property="Padding"
            Value="5" />
    <Setter Property="HorizontalContentAlignment"
            Value="Left" />
    <Setter Property="VerticalContentAlignment"
            Value="Top" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Label}">
                <Grid >
                    <Grid.Resources>
                        <LinearGradientBrush x:Key="HeaderBackgroundOpacityMask" StartPoint="0,0" EndPoint="1,0">
                            <GradientStop Color="Black"  Offset="0"/>
                            <GradientStop Color="Black" Offset="0.5"/>
                            <GradientStop Color="Transparent" Offset="1"/>
                        </LinearGradientBrush>
                    </Grid.Resources>

                    <Canvas x:Name="Canvas" 
                            ClipToBounds="True" 
                            DockPanel.Dock="Top"  
                            Height="{Binding ElementName=Content, Path=ActualHeight}">

                        <Border 
                            BorderBrush="{TemplateBinding BorderBrush}"
                            Canvas.Right="0"
                            Canvas.ZIndex="0"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}"
                            Padding="{TemplateBinding Padding}"
                            MinWidth="{Binding ElementName=Canvas, Path=ActualWidth}"
                            SnapsToDevicePixels="true"
                            x:Name="Content"
                        >
                            <ContentPresenter
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                Content="{Binding RelativeSource={RelativeSource AncestorType=Label}, Path=Content}"
                                RecognizesAccessKey="True"
                                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                            >
                                <ContentPresenter.Resources>
                                    <Style TargetType="TextBlock">
                                        <Setter Property="FontSize" Value="{Binding FontSize, RelativeSource={RelativeSource AncestorType={x:Type Label}}}"/> 
                                        <Setter Property="FontWeight" Value="{Binding FontWeight, RelativeSource={RelativeSource AncestorType={x:Type Label}}}"/> 
                                        <Setter Property="FontStyle" Value="{Binding FontStyle, RelativeSource={RelativeSource AncestorType={x:Type Label}}}"/> 
                                        <Setter Property="FontFamily" Value="{Binding FontFamily, RelativeSource={RelativeSource AncestorType={x:Type Label}}}"/> 
                                    </Style>
                                </ContentPresenter.Resources>

                            </ContentPresenter>
                        </Border>
                        <Label 
                            x:Name="Ellipses" 
                            Canvas.Left="0" 
                            Canvas.ZIndex="10"
                            FontWeight="{TemplateBinding FontWeight}"
                            FontSize="{TemplateBinding FontSize}"
                            FontFamily="{TemplateBinding FontFamily}"
                            FontStyle="{TemplateBinding FontStyle}"
                            VerticalContentAlignment="Center" 
                            OpacityMask="{StaticResource HeaderBackgroundOpacityMask}" 
                            Background="{TemplateBinding Background}"
                            Foreground="RoyalBlue"
                            Height="{Binding ElementName=Content, Path=ActualHeight}" 
                            Content="...&#160;&#160;&#160;">
                            <Label.Resources>
                                <Style TargetType="Label">
                                    <Style.Triggers>
                                        <DataTrigger Value="true">
                                            <DataTrigger.Binding>
                                                <MultiBinding Converter="{StaticResource GteConverter}">
                                                    <Binding ElementName="Canvas" Path="ActualWidth"/>
                                                    <Binding ElementName="Content" Path="ActualWidth"/>
                                                </MultiBinding>
                                            </DataTrigger.Binding>
                                            <Setter Property="Visibility" Value="Hidden"/>
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </Label.Resources>

                        </Label>
                    </Canvas>

                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled"
                             Value="false">
                        <Setter Property="Foreground"
                                Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Здесь есть несколько классов полезности.

GteConverter

<c:GteConverter x:Key="GteConverter"/>

который

public class RelationalValueConverter : IMultiValueConverter
{
    public enum RelationsEnum
    {
        Gt,Lt,Gte,Lte,Eq,Neq
    }

    public RelationsEnum Relations { get; protected set; }

    public RelationalValueConverter(RelationsEnum relations)
    {
        Relations = relations;
    }

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if(values.Length!=2)
            throw new ArgumentException(@"Must have two parameters", "values");

        var v0 = values[0] as IComparable;
        var v1 = values[1] as IComparable;

        if(v0==null || v1==null)
            throw new ArgumentException(@"Must arguments must be IComparible", "values");

        var r = v0.CompareTo(v1);

        switch (Relations)
        {
            case RelationsEnum.Gt:
                return r > 0;
                break;
            case RelationsEnum.Lt:
                return r < 0;
                break;
            case RelationsEnum.Gte:
                return r >= 0;
                break;
            case RelationsEnum.Lte:
                return r <= 0;
                break;
            case RelationsEnum.Eq:
                return r == 0;
                break;
            case RelationsEnum.Neq:
                return r != 0;
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

и

public class GtConverter : RelationalValueConverter
{
    public GtConverter() : base(RelationsEnum.Gt) { }
}
public class GteConverter : RelationalValueConverter
{
    public GteConverter() : base(RelationsEnum.Gte) { }
}
public class LtConverter : RelationalValueConverter
{
    public LtConverter() : base(RelationsEnum.Lt) { }
}
public class LteConverter : RelationalValueConverter
{
    public LteConverter() : base(RelationsEnum.Lte) { }
}
public class EqConverter : RelationalValueConverter
{
    public EqConverter() : base(RelationsEnum.Eq) { }
}
public class NeqConverter : RelationalValueConverter
{
    public NeqConverter() : base(RelationsEnum.Neq) { }
}

Вот он работает.

enter image description hereenter image description hereenter image description here

Ответ 4

Я не знаю, является ли это опечаткой, но вам не хватает full stop в конце вашего "желаемого результата". Я предполагаю, что вы этого не хотите. Поскольку вы знаете, сколько символов должно отображаться, вы можете просто получить подстроку всей строки и отобразить ее. Например,

string origText = "A very long text that requires trimming.";

//15 because the first three characters are replaced
const int MAXCHARACTERS = 15;

//MAXCHARACTERS - 1 because you don't want the full stop
string sub = origText.SubString(origText.Length-MAXCHARACTERS, MAXCHARACTERS-1);

string finalString = "..." + sub;
textBlock.Text = finalString;

Если вы не знаете, сколько символов вы хотите использовать в расширенном режиме, вы можете выполнить вычисление, чтобы определить его. В вашем примере ширина 80 приводит к символам 17, вы можете использовать это соотношение при изменении ширины.

Ответ 5

Вам нужно будет создать этот эффект самостоятельно. @KeyboardP дает ответ о том, как сделать обрезку, однако более сложная часть - это то, насколько важно обрезать. Вероятно, лучшим решением является взятие некоторого кода, найденного в Интернете, который обеспечивал обрезку текста, прежде чем он был добавлен в среду Silverlight. Например:

http://nerdplusart.com/texttrimming-textblock-for-silverlight

Это будет небольшая работа, однако ее адаптация не должна быть слишком сложной,