TextBox 의 내용이 짤릴 경우에만, ToolTip 보이기




목차


이 포스팅은 StackOverflow 사이트를 돌아다니다가, Question 을 보고 만들어본 내용입니다.

질문의 내용은 "Display tooltip if text is exceeds the available width of textbox" 였습니다. 그래서 답변도 해 줄겸 감사겸사 만들어 보았습니다 :)




개요


사실 이 문제를 해결하는데는 여러가지가 있습니다.

TextBox 의 사이즈가 변경 될 때마다, 이벤트 핸들링을 해서 MeasuredSize 와 ActualSize 를 비교해도 됩니다. 이게 글쓴이의 방식이었는데 여기에는 다소 문제가 있습니다. 창이 커진다거나 초기에는 핸들링할 방법이 없지요. 그 이외에도 예외 요소가 좀 있습니다. 사실 제가 이런 UI 동작을 이벤트 핸들링을 해서 작업하는것도 선호하진 않고요.


그래서 구현한 방법은 TextBox 안에 있는 ScrollViewer 를 이용하는 것입니다. TextBox 의 Visual 안에는 ScrollViewer 가 있습니다. 그렇기 때문에 텍스트가 넘어갔을 경우, 마우스로 드래그를 해서 이동(scroll) 할 수 있는 것이지요. 저는 이 ScrollViewer 의 ScrollableWidth Property 를 Binding 하여 해결하였습니다.

동작은 Behavior 를 통해서 수행됩니다. 따로 Behavior 클래스를 빼지 않고, 그냥 MainWindow.cs 안에 넣었습니다. 테스트 용도라서요 ^^;


참, 중요한 부분은 처음 Behavior 가 달라붙는 시점에서는 TextBox 의 Visual 이 다 만들어지지 않았기 때문에, ScrollViewer 에 접근이 불가능합니다. 그래서 Load 가 완료된 이후에 ScrollViewer 를 찾고 Binding 을 시도합니다.



    [MainWindow.xaml]

<window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:study="clr-namespace:Study" xmlns:objectmodel="clr-namespace:System.Collections.ObjectModel;assembly=System" xmlns:themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" x:class="Study.MainWindow" title="MainWindow" height="350" width="525">
    <grid>
        <grid.rowdefinitions>
            <rowdefinition height="Auto">
            <rowdefinition height="10">
            <rowdefinition height="Auto">
        </rowdefinition></rowdefinition></rowdefinition></grid.rowdefinitions>
        <grid.columndefinitions>
            <columndefinition width="*">
            <columndefinition width="*">
        </columndefinition></columndefinition></grid.columndefinitions>
        <textbox text="This is very long text.This is very long text.This is very long text." horizontalalignment="Right" x:name="PART_Textbox">
            <i:interaction.behaviors>
                <study:optionaltooltipbehavior>
            </study:optionaltooltipbehavior></i:interaction.behaviors>
        </textbox>
        <textbox text="This is sort text." grid.row="2" horizontalalignment="Right">
            <i:interaction.behaviors>
                <study:optionaltooltipbehavior>
            </study:optionaltooltipbehavior></i:interaction.behaviors>
        </textbox>
    </grid>
</window>



    [MainWindow.cs]


namespace Study
{
    /// 
    /// Interaction logic for MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
        }
    }


    public class OptionalToolTipBehavior : Behavior
    {
        protected override void OnAttached()
        {
            this.AssociatedObject.Loaded += AssociatedObject_Loaded;
            base.OnAttached();
        }


        void AssociatedObject_Loaded(object sender, EventArgs e)
        {
            this.AssociatedObject.Loaded -= AssociatedObject_Loaded;

            ScrollViewer scrollViewer = this.FindScrollViewer(AssociatedObject);
            if (scrollViewer != null)
            {
                this.AssociatedObject.SetBinding(TextBox.ToolTipProperty,
                    new Binding() { Source = scrollViewer, 
                        Path = new PropertyPath(ScrollViewer.ScrollableWidthProperty), 
                            Converter = ScrollableWithToTooltipConverter.Instance, 
                            ConverterParameter=this.AssociatedObject.Text});
            }
        }



        private ScrollViewer FindScrollViewer(DependencyObject element)
        {
            if (element is ScrollViewer) { return element as ScrollViewer; }

            int childCount = VisualTreeHelper.GetChildrenCount(element);
            for (int i = 0; i < childCount; i++)
            {
                return this.FindScrollViewer(VisualTreeHelper.GetChild(element, i));
            }
            return null;
        }



        private class ScrollableWithToTooltipConverter : IValueConverter
        {
            public static readonly ScrollableWithToTooltipConverter Instance = new ScrollableWithToTooltipConverter();

            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if((double) value > 0)
                {
                    return parameter.ToString();
                }
                return null;
            }


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

    }
}








'Microsoft > WPF' 카테고리의 다른 글

360 파노라마 뷰어  (4) 2014.12.19
Draggable Canvas ver 0.9  (1) 2014.11.17
편집용 Canvas 만들기  (0) 2014.11.16
Expanding Canvas 만들기 2  (0) 2014.11.16
격자 배경 그리기  (0) 2014.11.14