开发者

Silverlight 4 textbox does not show all content

Sometimes when I use a textbox it is not possible to scroll all the way down to see the last words.

I've included an example with three textboxes with identical content, but different widths. The one to the left does not show all words.

Move to the end of a textbox by selecting it and then press 'ctrl'+'end'. When I do this for the textbox to the left ('_tb1'), I cannot see the cursor and I cannot see the last words. It seems as the cursor and words are 'below' the textbox. I can though mark and copy the text that is not shown. The last word should be "si+", see code below. I've verified that the 'Text' property of the textbox contains all text.

This has so far only happened when I use 'TextWrapping="Wrap"' and for certain widths.

Any suggestions on how to fix it?

Silverlight 4 textbox does not show all content

<UserControl x:Class="Silverlight4TextBoxProblem.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid Width="500" Height="150">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBox Name="_tb1" Grid.Column="0" TextWrapping="Wrap" 
                 FontFamily="Arial" FontSize="12"
                 VerticalScrollBarVisibility="Visible"
                 Width="100"/>
        <TextBox Name="_tb2" Grid.Column="1" TextWrapping="Wrap" 
                 FontFamily="Arial" FontSize="12" 
                 VerticalScrollBarVisibility="Visible"
                 Width="75"/>
        <TextBox Name="_tb3" Grid.Column="2" TextWrapping="Wrap" 
                 FontFamily="Arial" FontSize="12"
                 VerticalScrollBarVisibility="Visible"
                 Width="150"/>
        <Button Grid.Column="3" Click="ButtonClick" Content="Assert _tb1"/>
    </Grid>
</UserControl>

Code-behind

public partial class MainPage : UserControl
{
    private readonly string ErrorText = @"Lorem ipsum dolor sit amet+++," + Environment.NewLine 
        + "consectetur adipisicing elit, sed do eiusmod" + Environment.NewLine
        + "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam," + Environment.NewLine
        + "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo" + Environment.NewLine
        + "consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse" + Environment.NewLine
        + "cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non" + Environment.NewLine
        + "proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem" + Environment.NewLine
        + "ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor" + Environment.NewLine
        + "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis" + Environment.NewLine
        + "nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." + Environment.NewLine
        + "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu" + Environment.NewLine
        + "fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in" + Environment.NewLine
        + "culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit" + Environment.NewLine
        + "amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore" + Environment.NewLine
      开发者_JAVA百科  + "et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation" + Environment.NewLine
        + "ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor" + Environment.NewLine
        + "in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla" + Environment.NewLine
        + "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui" + Environment.NewLine
        + "officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet," + Environment.NewLine
        + "consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et" + Environment.NewLine
        + "dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco" + Environment.NewLine
        + "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in" + Environment.NewLine
        + "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur." + Environment.NewLine
        + "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia" + Environment.NewLine
        + "deserunt mollit anim id est laborum. Lorem ipsum dolor si+";

    public MainPage()
    {
        InitializeComponent();

        _tb1.Text = ErrorText;
        _tb2.Text = ErrorText;
        _tb3.Text = ErrorText;
    }

    private void ButtonClick(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(_tb1.Text.Last().ToString());
    }
}


So I´ve had the exact same propblem. Depending on you requirements this can be solved by using a RichTextBox instead. And as a bonus it appears as if you get faster scrolling.

However, a RTB doesn´t have a text property or a max length property to bind to. I solved this by inheriting a RTB to my CustomTextBox.

If you hook up to the event contentchanged

public class CustomTextBox : RichTextBox
{
    public CustomTextBox()
    {
        ContentChanged += HandleContentChanged;
    }
...

and then

private void HandleContentChanged(object sender, ContentChangedEventArgs e)
{
    var text = GetContent(out blocks);
    Text = text;
}

and add the TextProperty to bind to

public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(CustomTextBox), new PropertyMetadata(string.Empty, HandleTextChanged));

    private static void HandleTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var customTextBox = (CustomTextBox)d;

        var newValue = (string)e.NewValue;

        //This method is only run when set from codebehind
        UpdateOnTextChange(customTextBox, newValue);
    }

    private static void UpdateOnTextChange(CustomTextBox customTextBox, string newValue)
    {
        int blocks;

        if (customTextBox.GetContent(out blocks) != newValue)
        {
            var binding = customTextBox.GetBindingExpression(TextProperty);

            customTextBox.Blocks.Clear();
            var value = EnsureString(newValue);
            customTextBox.Selection.Text = value;

            if (customTextBox.HasTextChanges)
            {
                customTextBox.HasTextChanges = false;
                //reset binding... 
                if (binding != null)
                {
                    customTextBox.SetBinding(TextProperty, binding.ParentBinding);
                }
            }

            var bindingExpression = customTextBox.GetBindingExpression(TextProperty);

            if (bindingExpression != null)
                bindingExpression.UpdateSource();
        }
    }

And since you will want to be able to get the content of the CustomTextBox as a string:

    public string GetContent(out int blocks)
    {
        var builder = new StringBuilder();
        blocks = 0;
        foreach (var run in Blocks.OfType<Paragraph>().Select(paragraph => paragraph.Inlines.FirstOrDefault()).OfType<Run>())
        {
            blocks++;
            builder.Append(run.Text);
            builder.Append(Environment.NewLine);
        }
        var content = builder.ToString();
        if (content.EndsWith(Environment.NewLine, StringComparison.CurrentCulture))
            content = content.Substring(0, content.Length - 2);
        return content ?? string.Empty;
    }


Wow, this is really a bug! It seems that the problem is with the TextBoxView internal control. It doesn't calculate the text properly for some situations. You can see the actual source of the problem using Silverlight Spy.

I tried hard finding a workaround for the problem but could not find one. I tried messing around with the Template and nothing works 100% of the time.

We should report that issue to Microsoft.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜