从类创建属性

时间:2015-06-09 12:28:53

标签: c# wpf xaml

我创建了一个类,它缩短文本以适应文本框,同时还添加“...”。

示例:

[ThisTextis]toolong > [ThisTex...]

我在Windows 8.1 VM(虚拟机)上使用Microsoft Visual Studio 2013,该软件是一个应用程序。

现在它可能并不完美,但这一切都很精彩。我现在想知道的是,如果我可以在该类之外创建一个布尔属性,那么用户可以在XAML中的文本框上启用/禁用它:

<TextBox CutText="True"/>

问题是我已经在类中使用了预先存在的Text属性,而且我的代码并不像我希望的那样漂亮。 无论如何,我会很高兴得到任何建议和/或帮助。

编辑:简单地说,我想为TextBlock.TextTrimming创建TextBox属性,因为现有属性仅限于TextBlock

这是班级:

 class CutText
    {
        //Create a new instance of a textbox
        TextBox textCut = new TextBox();

        //Reset at start
        public void ResetText(TextBox text)
        {
            //Overwrite textCut with the chosen TextBox
            textCut = text;
            //Handles the possibility of already filled textbox
            if (textCut.Text != "" || textCut.Text != null)
            {
                _text = textCut.Text;
            }
            //Prevents text from being 'Null' 
            else
            {
                _text = "";
            }
        }

        //Cuts text to width of textbox
        private string CutTextToWidth(string text, double fontSize, double width)
        {
            //boolean to check if width of text is correct
            bool validArea = false;
            //comply with difference in width of characters 
            double CharDiffLength = (stringWidth("M", fontSize) - stringWidth("|", fontSize));
            //shortened text
            string shortText = text;
            //last length which was too long
            int LastLongLen = text.Length;
            //last length which fit into textbox
            int LastFitLen = 0; 

            if (stringWidth(text, fontSize) < width)
            {
                shortText = text;
            }
            else
            {
                //repeat until the text fits into the appointed area
                while (!validArea)
                {
                    if (width < stringWidth(shortText, fontSize))
                    {
                        //text is still too long
                        LastLongLen = shortText.Length;
                    }
                    else
                    {
                        //text is not too long
                        LastFitLen = shortText.Length;
                    }

                    int newLen = (LastFitLen + LastLongLen) / 2;

                    if (shortText.Length != newLen)
                    {
                        //set shortened text
                        shortText = text.Substring(0, newLen) + "\u2026";
                    }
                    validArea = ((width - 10 < stringWidth(shortText, fontSize)) && (stringWidth(shortText, fontSize) < width));
                }
            }
            //return the shortened text
            return shortText;
        }

        //Calculate the width of the text
        private double stringWidth(string s, double fontSize)
        {
            if (s == " ")
                s = "\u00a0";

            TextBlock t = new TextBlock()
            {
                FontSize = fontSize,
                Text = s
            };
            t.Measure(new Size(double.MaxValue, double.MaxValue));
            return t.ActualWidth;
        }

        //(GotFocus) Replaces cut text with full text and places the cursor at the chosen position
        public void GotFocusText()
        {
            int index = textCut.SelectionStart;
            textCut.Text = _text;
            textCut.SelectionStart = index;
        }

        //(LostFocus) Saves cut text into property / empties the textbox if nothing has been written and sets tooltip
        public void LostFocusText()
        {
            if (!string.IsNullOrWhiteSpace(textCut.Text))
            {
                Text = textCut.Text;
            }
            else
            {
                Text = "";
            }
            ToolTipService.SetToolTip(textCut, _text);
        }

        //TextBox.Text Property
        private string _text;
        public string Text
        {
            get { return _text; }
            set
            {
                _text = value;
                //Receive text, fontsize and width of textbox
                textCut.Text = CutTextToWidth(_text, textCut.FontSize, textCut.Width - 25);
            }
        }
    }

3 个答案:

答案 0 :(得分:4)

我很遗憾地通知你,你浪费了你的时间。 WPF已经内置了该功能。您可以将TextBlock.TextTrimming property设置为CharacterEllipsisWordEllipsis,这将自动修剪控件的溢出文本并添加省略号(... )。看到这个简单的例子:

<TextBlock TextTrimming="CharacterEllipsis" Width="150">
    Lorem ipsum dolor sit amet, consectetur adipisicing</TextBlock>

来自MSDN上的TextTrimming Enumeration页:

  

CharacterEllipsis:文字在字符边界处被修剪。绘制省略号(...)代替剩余文本。

     

WordEllipsis:文字在字边界处被修剪。绘制省略号(...)代替剩余文本。

更新&gt;&gt;&gt;

要更直接地回答您的问题,您应该在Attached Property中创建代码。这样,您可以定义bool附加属性以使用省略号,例如。像这样的东西:

<TextBox TextBoxProperties.CutText="True" />

...其中TextBoxProperties将是定义附加属性的类的名称,CutText将是属性本身的名称。请参阅链接页面中的How to create an Attached Property section以了解如何执行此操作。您可以使用该属性中的CutText类。

答案 1 :(得分:2)

使用其他答案中的建议,我编写了一个对您有用的Custom Control

public class TrimmedTextBox : TextBox
{
    public bool Trim
    {
        get { return (bool)GetValue(TrimProperty); }
        set { SetValue(TrimProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Trim.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TrimProperty =
        DependencyProperty.Register("Trim", typeof(bool), typeof(TrimmedTextBox), new PropertyMetadata(true));

    public TextTrimming Trimming
    {
        get { return (TextTrimming)GetValue(TrimmingProperty); }
        set { SetValue(TrimmingProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Trimming.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TrimmingProperty =
        DependencyProperty.Register("Trimming", typeof(TextTrimming), typeof(TrimmedTextBox), new PropertyMetadata(TextTrimming.CharacterEllipsis));

    static TrimmedTextBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(TrimmedTextBox), new FrameworkPropertyMetadata(typeof(TrimmedTextBox)));
    }
}

Style

<Style TargetType="{x:Type local:TrimmedTextBox}"
       BasedOn="{StaticResource {x:Type TextBox}}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:TrimmedTextBox}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <ScrollViewer x:Name="PART_ContentHost"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsKeyboardFocused" Value="False"/>
                <Condition Property="Trim" Value="True"/>
            </MultiTrigger.Conditions>

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TextBox">
                        <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                            <TextBlock Text="{TemplateBinding Text}" 
                                       TextTrimming="{Binding Trimming, RelativeSource={RelativeSource TemplatedParent}}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </MultiTrigger>
    </Style.Triggers>
</Style>

用法:

<local:TrimmedTextBox Trim="True" 
                      Text="Le toucan has arrived" 
                      Width="50" 
                      Trimming="CharacterEllipsis"/>

你可能不得不玩风格来获得理想的外观和感觉,但这个想法仍然存在。这是一个Control Template,它扩展了TextBox,可让您设置是否希望文本框修剪内容以及您需要修剪的类型。

有关Custom Controls的详细信息,请参阅here

答案 2 :(得分:0)

既不可能,也不必做你想做的事。您无法向现有组件添加新属性。另外,如果你check out this answer to another question,通过为TextBox定义WPF样式,有一种更简单的方法来实现你想要做的事。