TextBlock 텍스트가 트리밍되고 있는지 확인하려면 어떻게 해야 합니까?
다음 텍스트 블록은 예상대로 랩 및 트리밍됩니다.텍스트가 잘릴 때 생략 기호 "..."가 표시됩니다.
<TextBlock
MaxWidth="60"
MaxHeight="60"
Text="This is some long text which I would like to wrap."
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis" />
텍스트 위에 텍스트가 잘린 경우에만 전체 텍스트와 함께 도구 설명을 표시합니다.「...」가 표시되고 있는지 아닌지를 어떻게 확실히 판단할 수 있을지 모르겠습니다.
텍스트가 트리밍되고 있는지 여부를 확인하려면 어떻게 해야 합니까?
알렉의 답변에 있는 링크가 다운되었기 때문에 웨이백 머신에서 링크의 캐시된 복사본을 찾았습니다.기사에 링크된 코드를 다운로드할 수 없으므로 코드 사전 조립 버전을 알려드립니다.작동하려고 하다가 한두 가지 문제가 발생했기 때문에 이 코드는 기사의 예시와 약간 다릅니다.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace TextBlockService
{
//Based on the project from http://web.archive.org/web/20130316081653/http://tranxcoder.wordpress.com/2008/10/12/customizing-lookful-wpf-controls-take-2/
public static class TextBlockService
{
static TextBlockService()
{
// Register for the SizeChanged event on all TextBlocks, even if the event was handled.
EventManager.RegisterClassHandler(
typeof(TextBlock),
FrameworkElement.SizeChangedEvent,
new SizeChangedEventHandler(OnTextBlockSizeChanged),
true);
}
private static readonly DependencyPropertyKey IsTextTrimmedKey = DependencyProperty.RegisterAttachedReadOnly("IsTextTrimmed",
typeof(bool),
typeof(TextBlockService),
new PropertyMetadata(false));
public static readonly DependencyProperty IsTextTrimmedProperty = IsTextTrimmedKey.DependencyProperty;
[AttachedPropertyBrowsableForType(typeof(TextBlock))]
public static Boolean GetIsTextTrimmed(TextBlock target)
{
return (Boolean)target.GetValue(IsTextTrimmedProperty);
}
public static readonly DependencyProperty AutomaticToolTipEnabledProperty = DependencyProperty.RegisterAttached(
"AutomaticToolTipEnabled",
typeof(bool),
typeof(TextBlockService),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
[AttachedPropertyBrowsableForType(typeof(DependencyObject))]
public static Boolean GetAutomaticToolTipEnabled(DependencyObject element)
{
if (null == element)
{
throw new ArgumentNullException("element");
}
return (bool)element.GetValue(AutomaticToolTipEnabledProperty);
}
public static void SetAutomaticToolTipEnabled(DependencyObject element, bool value)
{
if (null == element)
{
throw new ArgumentNullException("element");
}
element.SetValue(AutomaticToolTipEnabledProperty, value);
}
private static void OnTextBlockSizeChanged(object sender, SizeChangedEventArgs e)
{
TriggerTextRecalculation(sender);
}
private static void TriggerTextRecalculation(object sender)
{
var textBlock = sender as TextBlock;
if (null == textBlock)
{
return;
}
if (TextTrimming.None == textBlock.TextTrimming)
{
textBlock.SetValue(IsTextTrimmedKey, false);
}
else
{
//If this function is called before databinding has finished the tooltip will never show.
//This invoke defers the calculation of the text trimming till after all current pending databinding
//has completed.
var isTextTrimmed = textBlock.Dispatcher.Invoke(() => CalculateIsTextTrimmed(textBlock), DispatcherPriority.DataBind);
textBlock.SetValue(IsTextTrimmedKey, isTextTrimmed);
}
}
private static bool CalculateIsTextTrimmed(TextBlock textBlock)
{
if (!textBlock.IsArrangeValid)
{
return GetIsTextTrimmed(textBlock);
}
Typeface typeface = new Typeface(
textBlock.FontFamily,
textBlock.FontStyle,
textBlock.FontWeight,
textBlock.FontStretch);
// FormattedText is used to measure the whole width of the text held up by TextBlock container
FormattedText formattedText = new FormattedText(
textBlock.Text,
System.Threading.Thread.CurrentThread.CurrentCulture,
textBlock.FlowDirection,
typeface,
textBlock.FontSize,
textBlock.Foreground);
formattedText.MaxTextWidth = textBlock.ActualWidth;
// When the maximum text width of the FormattedText instance is set to the actual
// width of the textBlock, if the textBlock is being trimmed to fit then the formatted
// text will report a larger height than the textBlock. Should work whether the
// textBlock is single or multi-line.
// The "formattedText.MinWidth > formattedText.MaxTextWidth" check detects if any
// single line is too long to fit within the text area, this can only happen if there is a
// long span of text with no spaces.
return (formattedText.Height > textBlock.ActualHeight || formattedText.MinWidth > formattedText.MaxTextWidth);
}
}
}
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tbs="clr-namespace:TextBlockService">
<!--
Rather than forcing *all* TextBlocks to adopt TextBlockService styles,
using x:Key allows a more friendly opt-in model.
-->
<Style TargetType="TextBlock" x:Key="TextBlockService">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="tbs:TextBlockService.AutomaticToolTipEnabled" Value="True" />
<Condition Property="tbs:TextBlockService.IsTextTrimmed" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=Text}" />
</MultiTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
최근에는 WPF를 많이 하지 않았기 때문에 이것이 당신이 찾고 있는 것인지 잘 모르겠습니다만, 다음 기사를 확인해 주십시오.「외관적인」WPF 컨트롤의 커스터마이즈– Take 2 。조금 복잡하지만, 당신이 묻고 있는 것과 같은 질문을 다루고 있는 것 같습니다.업데이트: 웹사이트가 없어진 것 같습니다만, 아카이브에서 문서를 찾을 수 있습니다.Scott Chamberlain의 답변과 샘플 코드를 참조하십시오(Scott 감사합니다).
TextBlock이 ListBoxItem DataTemplate의 일부인 경우에는 위의 솔루션이 작동하지 않았습니다.다른 솔루션을 제안합니다.
public class MyTextBlock : System.Windows.Controls.TextBlock
{
protected override void OnToolTipOpening(WinControls.ToolTipEventArgs e)
{
if (TextTrimming != TextTrimming.None)
{
e.Handled = !IsTextTrimmed();
}
}
private bool IsTextTrimmed()
{
Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
return ActualWidth < DesiredSize.Width;
}
}
XAML:
<MyTextBlock Text="{Binding Text}" TextTrimming="CharacterEllipsis" ToolTip="{Binding Text}" />
Bidy의 대답에 따라 확대됩니다.이렇게 하면 모든 텍스트가 표시되지 않을 때만 툴팁을 표시하는 TextBlock이 생성됩니다.툴팁은 내용에 맞게 크기가 조정됩니다(텍스트가 잘린 상태에서 한 줄 상자 상태로 유지되는 기본 툴팁과는 반대).
using System;
using System.Windows;
using System.Windows.Controls;
namespace MyComponents
{
public class CustomTextBlock : TextBlock
{
protected override void OnInitialized(EventArgs e)
{
// we want a tooltip that resizes to the contents -- a textblock with TextWrapping.Wrap will do that
var toolTipTextBlock = new TextBlock();
toolTipTextBlock.TextWrapping = TextWrapping.Wrap;
// bind the tooltip text to the current textblock Text binding
var binding = GetBindingExpression(TextProperty);
if (binding != null)
{
toolTipTextBlock.SetBinding(TextProperty, binding.ParentBinding);
}
var toolTipPanel = new StackPanel();
toolTipPanel.Children.Add(toolTipTextBlock);
ToolTip = toolTipPanel;
base.OnInitialized(e);
}
protected override void OnToolTipOpening(ToolTipEventArgs e)
{
if (TextTrimming != TextTrimming.None)
{
e.Handled = !IsTextTrimmed();
}
}
private bool IsTextTrimmed()
{
Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
return ActualWidth < DesiredSize.Width;
}
}
}
XAML 사용:
<Window ...
xmlns:components="clr-namespace:MyComponents"
... >
<components:CustomTextBlock Text="{Binding Details}" TextTrimming="CharacterEllipsis" />
Alex의 답변에 약간의 문제가 있어 텍스트 블록의 텍스트가 삭제되고 있는지 확인하기 위해 논리를 약간 변경해야 했습니다.
var formattedText = new FormattedText(
Text, System.Threading.Thread.CurrentThread.CurrentCulture, FlowDirection, typeface, FontSize,
Foreground, VisualTreeHelper.GetDpi( this ).PixelsPerDip ) { MaxTextWidth = ActualWidth };
//Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
return ( Math.Floor(formattedText.Height ) > ActualHeight || Math.Floor( formattedText.MinWidth ) > ActualWidth;
이건 나한테 딱 맞아.
생략 부호가 활성화된 텍스트 블록인 사용자 컨트롤을 정의했습니다.다음으로 OnMouseUp과 OnMouseDown의 2가지 함수를 정의하여 사용자가 오버플로우한 텍스트 블록을 클릭하면 전체 값이 포함된 툴팁이 표시되도록 했습니다.
이것은 OnMouseDown 함수입니다.
private void TextBlockWithToolTipView_OnMouseDown(
object sender,
MouseButtonEventArgs e )
{
var typeface = new Typeface(
FontFamily,
FontStyle,
FontWeight,
FontStretch);
var formattedText = new FormattedText(
Text, System.Threading.Thread.CurrentThread.CurrentCulture, FlowDirection, typeface, FontSize,
Foreground, VisualTreeHelper.GetDpi( this ).PixelsPerDip ) { MaxTextWidth = ActualWidth };
if (Math.Floor(formattedText.Height) > ActualHeight || Math.Floor(formattedText.MinWidth) > ActualWidth )
{
if( ToolTip is ToolTip tt )
{
{
if( tt.PlacementTarget == null )
{
tt.PlacementTarget = this;
}
tt.IsOpen = true;
e.Handled = true;
}
}
}
}
그리고 이게 Xaml 비트야
<TextBlock
ToolTipService.IsEnabled="True"
MouseDown="TextBlockWithToolTipView_OnMouseDown"
MouseLeave="TextBlockWithToolTipView_OnMouseLeave"
TextTrimming="CharacterEllipsis"
TextWrapping="WrapWithOverflow">
<TextBlock.ToolTip>
<ToolTip
DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}">
<TextBlock Text="{Binding Path=Text, Mode=OneWay }"
TextWrapping="Wrap"/>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
언급URL : https://stackoverflow.com/questions/1041820/how-can-i-determine-if-my-textblock-text-is-being-trimmed
'programing' 카테고리의 다른 글
| 실행 시 WPF 버튼의 이미지가 표시되지 않음 (0) | 2023.04.21 |
|---|---|
| azure brocredmessage는 타입을 모른 채 몸을 구한다. (0) | 2023.04.21 |
| azure 웹 앱 요청 시간 초과 증가 (0) | 2023.04.21 |
| SqlDataReader에서 데이터 읽기 (0) | 2023.04.21 |
| IP 주소가 'XXX'인 Windows Azure Client.XXX.XX.XX.XX'는 서버에 액세스할 수 없습니다. (0) | 2023.04.21 |