2015-06-09 3 views
1

Я создал класс, который сокращает текст, который вставляется в текстовое поле, а также добавляет «...».Создайте свойство из класса

Пример:

[ThisTextis]toolong > [ThisTex...]

Я использую Microsoft Visual Studio 2013 на Windows, 8.1 VM (Virtual Machine) и программное обеспечение является App.

Теперь это может быть не идеально, но это работает отлично и прекрасно. То, что я хочу знать сейчас, если я могу создать логическое свойство из этого класса, так что пользователь может включить/отключить его в текстовом поле в XAML:

<TextBox CutText="True"/> 

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

Edit: Проще говоря, я хочу, чтобы создать 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); 
      } 
     } 
    } 
+0

Это не совсем так ясно, чего вы пытаетесь достичь. Что вы хотите, дайте последовательность операций. –

+0

@JamesHarcourt Ну, просто поставьте, я хочу создать свойство, подобное свойству 'TextBlock.TextTrimming', но для TextBox, а не для TextBlock. – user3701907

ответ

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.

+0

Я не думал о создании настраиваемого элемента управления. (facepalm!) Большое спасибо. – user3701907

+0

Нет проблем! :-) –

4

Я сожалею, чтобы сообщить вам, что вы потратили свое время. WPF уже имеет встроенную функциональность. Вы можете установить TextBlock.TextTrimming property на CharacterEllipsis или WordEllipsis, и это будет автоматически обрезать переполняющий текст элемента управления и добавить многоточие (...). Смотрите этот простой пример:

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

С TextTrimming Enumeration страницы на MSDN:

CharacterEllipsis: Текст обрезан на границе символа. Вместо оставшегося текста делается эллипсис (...).

WordEllipsis: Текст обрезается на границе слова. Вместо оставшегося текста делается эллипсис (...).


UPDATE >>>

Чтобы ответить на ваш вопрос более непосредственно, вы должны создать свой код в Attached Property. Таким образом, вы можете определить bool Attached Property, чтобы использовать многоточие, например. что-то вроде этого:

<TextBox TextBoxProperties.CutText="True" /> 

... где TextBoxProperties будет имя класса, который определяет вложенное свойство и CutText бы имя самого свойства. См. Страницу How to create an Attached Property section со страницы, чтобы узнать, как это сделать. Вы можете использовать свой класс CutText из этого свойства.

+1

Я думаю, что он после «TextBox», а не «TextBlock». –

+0

К сожалению, встроенная функциональность существует только для TextBlocks, но не для TextBoxes, что также является причиной того, что я создал этот новый класс. – user3701907

+0

См. Вопрос [TextBox TextTrimming] (http://stackoverflow.com/questions/10227014/textbox-texttrimming) для решения. – Sheridan

0

Невозможно и не нужно делать то, что вы пытаетесь сделать. Вы не можете добавлять новые свойства к существующим компонентам. Кроме того, если вы check out this answer to another question, есть более простой способ добиться того, что вы хотите сделать, указав стиль WPF для TextBox.

+0

Кажется, мне пришлось бы найти другой путь. Спасибо за информацию. К сожалению, адаптация этого стиля в наших обстоятельствах невозможна, так как у нас будет сотни текстовых полей, что приведет к довольно грязному коду. – user3701907

Смежные вопросы