在<editor>

时间:2017-09-29 10:59:57

标签: c# xaml xamarin xamarin.forms

所以我正在寻找的是一个代码,它将检查用户是否写了一个特定的单词(Select,From,Where)。如果为true,则该单词的textcolor必须更改(TextChanged事件)。我不知道如何做到这一点,这是可能的。

我正在使用Xamarin.Forms并在Page.xaml中使用以下代码:

<Editor x:Name="qEditor" 
     Text="Input"
     TextChanged="Handle_TextChanged"
     BackgroundColor="White" 
     HorizontalOptions="FillAndExpand"
     HeightRequest="75"/>

因此,每当有人输入其中一个特定单词时,只有该单词的颜色必须直接变为红色。

Page.xaml.cs中的代码:

void Handle_TextChanged(object sender, TextChangedEventArgs e)
{
    string input = e.NewTextValue;
    string[] qInput = input.Split(' ');
    //Code here
}

我在Google和Stackoverflow以及found something上看了很多,但它使用的Contains对我的代码无效。

如果您对我需要更改的内容有任何建议,或者即使我必须更改上述代码的所有内容,请给我一些建议。该项目要求我仅使用C#Xamarin.Forms

2 个答案:

答案 0 :(得分:4)

Xamarin表单不支持开箱即用。

您必须扩展Editor控件才能添加对格式化文本的支持。这可以通过添加类型FormattedString的可绑定属性来完成。此控件将通过TextChanged事件监听文本更改来更新属性(在本例中我使用过Regex)。

由于FormattedText将是bindable-property,因此自定义平台呈现器可以检测到更改,并相应地将其呈现为Android中的Spannable和iOS中的AttributedString

enter image description here

表格控制

public class ExEditor : Editor
{
    public static readonly BindableProperty FormattedTextProperty =
        BindableProperty.Create(
            "FormattedText", typeof(FormattedString), typeof(ExEditor),
            defaultValue: default(FormattedString));

    public FormattedString FormattedText
    {
        get { return (FormattedString)GetValue(FormattedTextProperty); }
        set { SetValue(FormattedTextProperty, value); }
    }

    public ExEditor()
    {
        TextChanged += ExEditor_TextChanged;
    }

    void ExEditor_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (string.IsNullOrWhiteSpace(Text))
            return;

        var pattern = @"\b(SELECT|WHERE|AND|OR)\b";
        var words = Regex.Split(Text, pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline);

        var formattedString = new FormattedString();
        foreach (var word in words)
            formattedString.Spans.Add(new Span
            {
                Text = word,
                BackgroundColor = BackgroundColor,
                FontSize = FontSize,
                FontFamily = FontFamily,
                FontAttributes = FontAttributes,
                ForegroundColor = Regex.IsMatch(word, pattern, RegexOptions.IgnoreCase) ? Color.Red : TextColor
            });

        FormattedText = formattedString; 
    }       
}

iOS渲染器

[assembly: ExportRenderer(typeof(ExEditor), typeof(ExEditorRenderer))]
namespace SampleApp.iOS
{
    public class ExEditorRenderer : EditorRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
        {
            base.OnElementChanged(e);

            if (Control == null || Element == null)
                return;

            UpdateTextOnControl();
        }

        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == nameof(ExEditor.FormattedText)
                || e.PropertyName == nameof(Editor.FontFamily)
                || e.PropertyName == nameof(Editor.FontSize)
                || e.PropertyName == nameof(Editor.TextColor)
                || e.PropertyName == nameof(Editor.BackgroundColor)
                || e.PropertyName == nameof(Editor.FontAttributes))
                {
                    UpdateTextOnControl();
                }
        }

        void UpdateTextOnControl()
        {
            var caretPos = Control.GetOffsetFromPosition(Control.BeginningOfDocument, Control.SelectedTextRange.Start);

            if (Element is ExEditor formsElement)
                if (formsElement.FormattedText != null)
                    Control.AttributedText = formsElement.FormattedText.ToAttributed(new Font(), Element.TextColor);

            var newPosition = Control.GetPosition(Control.BeginningOfDocument, offset: caretPos);
            Control.SelectedTextRange = Control.GetTextRange(newPosition, newPosition);
        }
    }
}

Android渲染器

[assembly: ExportRenderer(typeof(ExEditor), typeof(ExEditorRenderer))]
namespace SampleApp.Android
{
    public class ExEditorRenderer : EditorRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
        {
            base.OnElementChanged(e);

            if (Control == null || Element == null)
                return;

            UpdateTextOnControl();
        }

        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == nameof(ExEditor.FormattedText)
                || e.PropertyName == nameof(Editor.FontFamily)
                || e.PropertyName == nameof(Editor.FontSize)
                || e.PropertyName == nameof(Editor.TextColor)
                || e.PropertyName == nameof(Editor.BackgroundColor)
                || e.PropertyName == nameof(Editor.FontAttributes))
            {
                UpdateTextOnControl();
            }
        }

        void UpdateTextOnControl()
        {
            var caretPos = Control.SelectionStart;

            if (Element is ExEditor formsElement)
                if (formsElement.FormattedText != null)
                    Control.SetText(formsElement.FormattedText.ToAttributed(new Font(), Element.TextColor, Control),
                                    TextView.BufferType.Spannable);

            Control.SetSelection(caretPos);
        }
    }
}

样本用法

<!-- make sure to map local prefix to control's namespace -->
<local:ExEditor Text="Select * from Table where text='1' and type='str'" 
        VerticalOptions="Start" />

答案 1 :(得分:1)

在这种情况下,您可以使用FormattedText

的属性Xamarin.Forms.Label

案例中的例子:

    private string[] wordsRed = { "Select", "From", "Where"}; // some examples
    private bool isSpecialColor = false;
    private Span span;

    /// <summary>
    /// Handles the text changed.
    /// </summary>
    /// <param name="sender">Sender.</param>
    /// <param name="e">E.</param>
    void Handle_TextChanged(object sender, TextChangedEventArgs e)
    {
        string input = e.NewTextValue;
        string[] qInput = input.Split(' ');

        CheckInput(qInput);
    }

    /// <summary>
    /// Checks the input.
    /// </summary>
    /// <param name="qInput">Q input.</param>
    private void CheckInput(string[] qInput)
    {
        // Check if the last typed character is a word separator.
        if (input[input.Length-1] == ' ') 
        {
            //
            // Loop through the string[] with the words you want to give a color on.
            //
            for (int i = 0; i < wordsRed.Length; i++)
            {
                //
                // Check on the last word that is typed
                //
                if (qInput[qInput.Length-1] == wordsRed[i])
                {
                    // Create a span with the word and color the foreground red
                    span = new Span
                    {
                        Text = qInput[qInput.Length-1] + " ",
                        ForegroundColor = Color.Green,
                    };

                    // Add the span to the Label
                    aLabel.FormattedText.Spans.Add(item: span);
                    // set boolean true because there is made a span with a red foreground.
                    isSpecialColor = true;
                }
                else
                {
                    // Do nothing.
                }
            }

            // Check if the word altready is colored.
            if (isSpecialColor)
            {
                // Set the boolean to false for the next check.
                isSpecialColor = false;
            }
            else
            {
                // Create span with the word and color it black.
                span = new Span
                {
                    Text = qInput[i] + " ",
                    ForegroundColor = Color.Black,
                };
                aLabel.FormattedText.Spans.Add(item: span);
            }
        }
        else 
        {                
            // Do nothing.
        }
    }