WPF XAML 如果文本不适合 TextBlock,则显示省略号
WPF XAML show ellipsis if text does not fit in TextBlock
如果我的文件名和路径不适合 TextBlock
,我想显示省略号。
例如,如果我的文件名和路径如下:
C:\examples\example\folderA\folderB\folderC\myfilename.txt
我想在我的 TextBlock
中这样显示它:
C:\examples...myfilename.txt
更新:
我知道我可以使用 TextTrimming
在末尾设置省略号。但是我需要一种在中间某处设置省略号的方法。
好的,我很想知道这是否可以只用基本的 XAML 来完成,而不是乱搞测量或绘图,所以开始乱搞。我今天没有时间完成这个,但我想我会作为你的起点分享给你,如果你愿意接受它并解决剩下的问题。
XAML 目前看起来是这样的:
<Window.Resources>
<local:FileNameConverter x:Key="FileNameConverter" />
<local:FilePathConverter x:Key="FilePathConverter" />
<Style x:Key="CustomFileText" TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="false">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<TextBox IsHitTestVisible="False" /> <!-- for Border -->
<DockPanel>
<TextBlock Text="{TemplateBinding Text, Converter={StaticResource FileNameConverter}}" DockPanel.Dock="Right" Margin="-3,3,4,3" />
<TextBlock Text="{TemplateBinding Text, Converter={StaticResource FilePathConverter}}" TextTrimming="CharacterEllipsis" Margin="4,3,0,3" />
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Margin="10">
<TextBox Text="C:\Program Files\Some Directory\SomeFile.txt" Style="{StaticResource CustomFileText}"/>
<TextBox Margin="0,10" />
</StackPanel>
最终结果是,如果 TextBox 具有编辑焦点,它将显示为普通 TextBox :
但是一旦用户将焦点移到表单的其他地方,它就会分成两个单独的 TextBlock,它们使用转换器来解析 Directory 和 FileName。目录中使用了 TextTrimming 以提供您在问题中描述的效果:
主要问题是在调整大小时,两个文本框之间添加了额外的 space。
这里我可以想到两个选项:
根据某种类型的触发器制作模板 "only use this template if TextBox.DesiredSize.Width > TextBox.ActualWidth
"
更改模板中的 XAML,使名称文本框以某种方式显示为 "take up all the space you need as your minimum size. If there is extra space, assign it to this box too",而目录文本框显示为 "take up all the space you can, but do not grow bigger than your contents"。我不确定执行此操作的最佳方法,但我想它与不同的面板、我现在无法想到的 TextBox 上的某些属性或一些限制大小的自定义 converter/binding 有关。
我猜 #1 会更容易实现,但我现在没有时间弄明白。希望这能给你一个好的起点,祝你好运! :)
哦,转换器非常基础。您可能想要添加更多保护措施,但这是我用于测试的内容:
public class FileNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && value is string)
return System.IO.Path.GetFileName((string)value);
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class FilePathConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && value is string)
return System.IO.Path.GetDirectoryName((string)value);
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
我修改了 Rachel 提供的 XAML 以修复出现在 window 尺寸上的路径中的额外 space。
<Window.Resources>
<local:FileNameConverter x:Key="FileNameConverter" />
<local:FilePathConverter x:Key="FilePathConverter" />
<Style x:Key="CustomFileText" TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="false">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<TextBox Grid.ColumnSpan="2" IsHitTestVisible="False"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="{Binding ActualWidth, ElementName=PART_DirMaxWidth}"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Canvas x:Name="PART_Canvas">
<TextBlock x:Name="PART_DirMaxWidth" Margin="0" Padding="0" Text="{TemplateBinding Text, Converter={StaticResource FilePathConverter}}" Visibility="Hidden"/>
<TextBlock Width="{Binding ActualWidth, ElementName=PART_Canvas}" Margin="0" Padding="0" Text="{TemplateBinding Text, Converter={StaticResource FilePathConverter}}" TextTrimming="CharacterEllipsis" Background="Transparent"/>
</Canvas>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<TextBlock Margin="0" Padding="0" Text="\" Background="Transparent"/>
<TextBlock Margin="0" Padding="0" Text="{TemplateBinding Text, Converter={StaticResource FileNameConverter}}" Background="Transparent"/>
</StackPanel>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
如果我的文件名和路径不适合 TextBlock
,我想显示省略号。
例如,如果我的文件名和路径如下:
C:\examples\example\folderA\folderB\folderC\myfilename.txt
我想在我的 TextBlock
中这样显示它:
C:\examples...myfilename.txt
更新:
我知道我可以使用 TextTrimming
在末尾设置省略号。但是我需要一种在中间某处设置省略号的方法。
好的,我很想知道这是否可以只用基本的 XAML 来完成,而不是乱搞测量或绘图,所以开始乱搞。我今天没有时间完成这个,但我想我会作为你的起点分享给你,如果你愿意接受它并解决剩下的问题。
XAML 目前看起来是这样的:
<Window.Resources>
<local:FileNameConverter x:Key="FileNameConverter" />
<local:FilePathConverter x:Key="FilePathConverter" />
<Style x:Key="CustomFileText" TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="false">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<TextBox IsHitTestVisible="False" /> <!-- for Border -->
<DockPanel>
<TextBlock Text="{TemplateBinding Text, Converter={StaticResource FileNameConverter}}" DockPanel.Dock="Right" Margin="-3,3,4,3" />
<TextBlock Text="{TemplateBinding Text, Converter={StaticResource FilePathConverter}}" TextTrimming="CharacterEllipsis" Margin="4,3,0,3" />
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Margin="10">
<TextBox Text="C:\Program Files\Some Directory\SomeFile.txt" Style="{StaticResource CustomFileText}"/>
<TextBox Margin="0,10" />
</StackPanel>
最终结果是,如果 TextBox 具有编辑焦点,它将显示为普通 TextBox :
但是一旦用户将焦点移到表单的其他地方,它就会分成两个单独的 TextBlock,它们使用转换器来解析 Directory 和 FileName。目录中使用了 TextTrimming 以提供您在问题中描述的效果:
主要问题是在调整大小时,两个文本框之间添加了额外的 space。
这里我可以想到两个选项:
根据某种类型的触发器制作模板 "only use this template if
TextBox.DesiredSize.Width > TextBox.ActualWidth
"更改模板中的 XAML,使名称文本框以某种方式显示为 "take up all the space you need as your minimum size. If there is extra space, assign it to this box too",而目录文本框显示为 "take up all the space you can, but do not grow bigger than your contents"。我不确定执行此操作的最佳方法,但我想它与不同的面板、我现在无法想到的 TextBox 上的某些属性或一些限制大小的自定义 converter/binding 有关。
我猜 #1 会更容易实现,但我现在没有时间弄明白。希望这能给你一个好的起点,祝你好运! :)
哦,转换器非常基础。您可能想要添加更多保护措施,但这是我用于测试的内容:
public class FileNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && value is string)
return System.IO.Path.GetFileName((string)value);
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class FilePathConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && value is string)
return System.IO.Path.GetDirectoryName((string)value);
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
我修改了 Rachel 提供的 XAML 以修复出现在 window 尺寸上的路径中的额外 space。
<Window.Resources>
<local:FileNameConverter x:Key="FileNameConverter" />
<local:FilePathConverter x:Key="FilePathConverter" />
<Style x:Key="CustomFileText" TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="false">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<TextBox Grid.ColumnSpan="2" IsHitTestVisible="False"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="{Binding ActualWidth, ElementName=PART_DirMaxWidth}"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Canvas x:Name="PART_Canvas">
<TextBlock x:Name="PART_DirMaxWidth" Margin="0" Padding="0" Text="{TemplateBinding Text, Converter={StaticResource FilePathConverter}}" Visibility="Hidden"/>
<TextBlock Width="{Binding ActualWidth, ElementName=PART_Canvas}" Margin="0" Padding="0" Text="{TemplateBinding Text, Converter={StaticResource FilePathConverter}}" TextTrimming="CharacterEllipsis" Background="Transparent"/>
</Canvas>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<TextBlock Margin="0" Padding="0" Text="\" Background="Transparent"/>
<TextBlock Margin="0" Padding="0" Text="{TemplateBinding Text, Converter={StaticResource FileNameConverter}}" Background="Transparent"/>
</StackPanel>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>