Home > Software design >  Xamarin Forms Editor Newline Handling Workaround
Xamarin Forms Editor Newline Handling Workaround

Time:10-11

The Text-property of the Editor type uses unexpected ways to represent newlines. In UWP on windows for example, it uses \r instead of \r\n as advertised by the Environment.NewLine property. This seems some platform specific behavior (however I would expected from UWP on windows \r\n).

The web shows some information about this problem, but a solution seems not to be available in the current version: https://github.com/xamarin/Xamarin.Forms/pull/6823 https://github.com/xamarin/Xamarin.Forms/issues/3020

I really would like to circumvent this behavior, so that I don't have to make some hacks into my view model processing.

I tried to create a IValueConverter which I use in the Binding and replace the bogus newlines. This works fine, however brings usability problems in the editor (cursor positioning begins to err). If I could set the UpdateSourceTrigger, this would work, however it seems that Xamarin does not support that.

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {            
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        if(value is string sv) {                
            if(sv.IndexOf("\r") > -1 && sv.IndexOf("\n") < 0) {             
                return sv.Replace("\r",Environment.NewLine);
            }
        }
        return value;
    }

Another thing I tried was, to add a handler to Editor.Completed. The problem with this is, that the binding executes after the event and hence my changes are undone.

private void TextContent_Completed(object sender, EventArgs e) {
  var vm= ...
  vm.TextContent= XamarinNewlineRestorer.TransformToClrSpecific(vm.TextContent);                
}

Does anyone know of a solution to this problem? Or am I misunderstanding somethin bigtime?

CodePudding user response:

The workaround is to do the replacement in the setter method of the property defined in viewmodel , and then bind it to the Editor .

Something like

  public string WorkAroundContent
        {
            get {
                switch (Device.RuntimePlatform)
                {
                    case Device.UWP:
                        return _Content.Replace("\n", "\r");
                    default:
                        return _Content;
                }
            }
            set
            {
                string newContent;
                switch (Device.RuntimePlatform)
                {
                    case Device.UWP:
                        newContent = value.Replace("\r", "\n");
                        break;
                    default:
                        newContent = value;
                        break;
                }

                if (_Content == newContent) return;
                Content = newContent;
            }
        }

Refer to https://github.com/xamarin/Xamarin.Forms/issues/3020#issuecomment-507332809.

CodePudding user response:

As I stated in my post, I don't like the idea to polute my view models. ColeX's answer however showed me where I erred.
The final solution was to create a value converter with the addition, that it changes the data in both directions. This was the error in my first try and brought the Xamarin Editor component out of pace. Here the solution for whom who is interested in a value converter-based solution, which I find desirable:

    public class XamarinWorkaroundNewlineValueConverter : IValueConverter {                
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
            if (value is string stringValue && targetType == typeof(string)) {
                switch (Device.RuntimePlatform) {
                    case Device.UWP:
                        return stringValue.Replace(Environment.NewLine, "\r");
                    default:
                        return stringValue;
                }
            }
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
            if(value is string stringValue && targetType==typeof(string)) {
                switch (Device.RuntimePlatform) {
                    case Device.UWP:
                        return stringValue.Replace("\r", Environment.NewLine);
                    default:
                        return stringValue;
                }
            }
            return value;
        }
    }

In App.xaml or the resource section of the view declare the converter:

<[your value converter namespace]:XamarinWorkaroundNewlineValueConverter x:Key="XamarinWorkaroundNewlineValueConverter"/>

In the view use it like this:

<Editor Text ="{Binding [YourTextPropertyName],Converter={StaticResource XamarinWorkaroundNewlineValueConverter}}" />
  • Related