--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.Github, 1678, "[Enhancement] Entry: Read-only entry", PlatformAffected.All)]
+ public class Issue1678
+ : TestContentPage
+ {
+ protected override void Init()
+ {
+ var entryText = "Entry Lorem Ipsum";
+ var editorText = "Editor Lorem Ipsum";
+
+ var entryDefaults = new Entry { Text = entryText };
+ var editorDefaults = new Editor { Text = editorText };
+ var entryReadOnly = new Entry { Text = entryText, IsReadOnly = true };
+ var editorReadOnly = new Editor { Text = editorText, IsReadOnly = true };
+ var entryToggleable = new Entry { Text = entryText };
+ var editorToggleable = new Editor { Text = editorText };
+
+ var toggle = new Switch { IsToggled = false };
+
+ var stackLayout = new StackLayout();
+ stackLayout.Children.Add(new Label { Text = "Defaults" });
+ stackLayout.Children.Add(entryDefaults);
+ stackLayout.Children.Add(editorDefaults);
+ stackLayout.Children.Add(new Label { Text = "Read Only" });
+ stackLayout.Children.Add(entryReadOnly);
+ stackLayout.Children.Add(editorReadOnly);
+ stackLayout.Children.Add(new Label { Text = "Toggleable is read only" });
+ stackLayout.Children.Add(entryToggleable);
+ stackLayout.Children.Add(editorToggleable);
+ stackLayout.Children.Add(toggle);
+
+ toggle.Toggled += (_, b) =>
+ {
+ entryToggleable.IsReadOnly = b.Value;
+ editorToggleable.IsReadOnly = b.Value;
+ };
+
+ stackLayout.Padding = new Thickness(0, 20, 0, 0);
+ Content = stackLayout;
+ }
+ }
+}
<Compile Include="$(MSBuildThisFileDirectory)Issue3788.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue1724.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3524.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Issue1678.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue2004.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3333.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue2338.cs" />
var maxLengthContainer = new ViewContainer<Editor>(Test.InputView.MaxLength, new Editor { MaxLength = 3 });
+ var readOnlyContainer = new ViewContainer<Editor>(Test.Editor.IsReadOnly, new Editor { Text = "This is read-only Editor", IsReadOnly = true });
+
Add(completedContainer);
Add(textContainer);
Add(textChangedContainer);
Add(textColorDisabledContainer);
Add(keyboardContainer);
Add(maxLengthContainer);
+ Add(readOnlyContainer);
}
}
}
\ No newline at end of file
var maxLengthContainer = new ViewContainer<Entry>(Test.InputView.MaxLength, new Entry { MaxLength = 3 });
+ var readOnlyContainer = new ViewContainer<Entry>(Test.Entry.IsReadOnly, new Entry { Text = "This is read-only Entry", IsReadOnly = true });
var isPasswordInputScopeContainer = new ViewContainer<Entry>(Test.Entry.IsPasswordNumeric, new Entry { Keyboard = Keyboard.Numeric });
var switchPasswordButton = new Button
{
Add (placeholderColorDisabledContainer);
Add (passwordColorContainer);
Add (maxLengthContainer);
+ Add (readOnlyContainer);
Add (isPasswordInputScopeContainer);
}
}
Assert.AreEqual (initialText, oldText);
Assert.AreEqual (finalText, newText);
}
+
+ [TestCase(true)]
+ public void IsReadOnlyTest(bool isReadOnly)
+ {
+ Editor editor = new Editor();
+ editor.SetValue(InputView.IsReadOnlyProperty, isReadOnly);
+ Assert.AreEqual(isReadOnly, editor.IsReadOnly);
+ }
+ [Test]
+ public void IsReadOnlyDefaultValueTest()
+ {
+ Editor editor = new Editor();
+ Assert.AreEqual(editor.IsReadOnly, false);
+ }
}
}
Assert.True(result == isEnabled ? true : false);
}
+
+ [TestCase(true)]
+ public void IsReadOnlyTest(bool isReadOnly)
+ {
+ Entry entry = new Entry();
+ entry.SetValue(InputView.IsReadOnlyProperty, isReadOnly);
+ Assert.AreEqual(isReadOnly, entry.IsReadOnly);
+ }
+
+ [Test]
+ public void IsReadOnlyDefaultValueTest()
+ {
+ Entry entry = new Entry();
+ Assert.AreEqual(entry.IsReadOnly, false);
+ }
}
}
new PropertyTestCase<TapGestureRecognizer, int> ("NumberOfTapsRequired", t => t.NumberOfTapsRequired, (t, o) => t.NumberOfTapsRequired = o, () => 1, 3),
new PropertyTestCase<TapGestureRecognizer, object> ("CommandParameter", t => t.CommandParameter, (t, o) => t.CommandParameter = o, () => null, "Test"),
new PropertyTestCase<TapGestureRecognizer, ICommand> ("Command", t => t.Command, (t, o) => t.Command = o, () => null, new Command(()=>{})),
- new PropertyTestCase<MasterDetailPage, bool> ("IsGestureEnabled", md => md.IsGestureEnabled, (md, v) => md.IsGestureEnabled = v, () => true, false)
+ new PropertyTestCase<MasterDetailPage, bool> ("IsGestureEnabled", md => md.IsGestureEnabled, (md, v) => md.IsGestureEnabled = v, () => true, false),
+ new PropertyTestCase<Entry, bool> ("IsReadOnly", v => v.IsReadOnly, (v, o) => v.IsReadOnly = o, () => false, true),
+ new PropertyTestCase<Editor, bool> ("IsReadOnly", v => v.IsReadOnly, (v, o) => v.IsReadOnly = o, () => false, true)
};
#pragma warning restore 0414
public static readonly BindableProperty MaxLengthProperty = BindableProperty.Create(nameof(MaxLength), typeof(int), typeof(int), int.MaxValue);
+ public static readonly BindableProperty IsReadOnlyProperty = BindableProperty.Create(nameof(IsReadOnly), typeof(bool), typeof(InputView), false);
+
public int MaxLength
{
get { return (int)GetValue(MaxLengthProperty); }
get { return (bool)GetValue(IsSpellCheckEnabledProperty); }
set { SetValue(IsSpellCheckEnabledProperty, value); }
}
+
+ public bool IsReadOnly
+ {
+ get { return (bool)GetValue(IsReadOnlyProperty); }
+ set { SetValue(IsReadOnlyProperty, value); }
+ }
}
}
\ No newline at end of file
FontAttributes,
FontFamily,
FontSize,
+ MaxLength,
+ IsReadOnly
}
public enum Entry
TextDisabledColor,
PlaceholderDisabledColor,
PasswordColor,
+ MaxLength,
+ IsReadOnly,
IsPasswordNumeric
}
UpdateMaxLength();
UpdatePlaceholderColor();
UpdatePlaceholderText();
+ UpdateIsReadOnly();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
UpdatePlaceholderText();
else if (e.PropertyName == Editor.PlaceholderColorProperty.PropertyName)
UpdatePlaceholderColor();
+ else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+ UpdateIsReadOnly();
base.OnElementPropertyChanged(sender, e);
}
if (currentControlText.Length > Element.MaxLength)
Control.Text = currentControlText.Substring(0, Element.MaxLength);
}
+
+ void UpdateIsReadOnly()
+ {
+ bool isReadOnly = !Element.IsReadOnly;
+
+ Control.FocusableInTouchMode = isReadOnly;
+ Control.Focusable = isReadOnly;
+ Control.SetCursorVisible(isReadOnly);
+ }
}
}
\ No newline at end of file
UpdateMaxLength();
UpdateImeOptions();
UpdateReturnType();
+ UpdateIsReadOnly();
if (_cursorPositionChangePending || _selectionLengthChangePending)
UpdateCursorSelection();
UpdateCursorSelection();
else if (e.PropertyName == Entry.CursorPositionProperty.PropertyName)
UpdateCursorSelection();
+ else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+ UpdateIsReadOnly();
base.OnElementPropertyChanged(sender, e);
}
if (_nativeSelectionIsUpdating || Control == null || Element == null)
return;
- if (Control.RequestFocus())
+ if (!Element.IsReadOnly && Control.RequestFocus())
{
try
{
_nativeSelectionIsUpdating = false;
}
}
+
+ void UpdateIsReadOnly()
+ {
+ bool isReadOnly = !Element.IsReadOnly;
+
+ Control.FocusableInTouchMode = isReadOnly;
+ Control.Focusable = isReadOnly;
+ Control.SetCursorVisible(isReadOnly);
+ }
}
-}
+}
\ No newline at end of file
UpdateTextColor();
UpdateEditable();
UpdateMaxLength();
+ UpdateIsReadOnly();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
UpdateFont();
else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
UpdateMaxLength();
+ else if (e.PropertyName == Xamarin.Forms.InputView.IsReadOnlyProperty.PropertyName)
+ UpdateIsReadOnly();
}
protected override void SetBackgroundColor(Color color)
if (currentControlText.Length > Element?.MaxLength)
Control.StringValue = currentControlText.Substring(0, Element.MaxLength);
}
+
+ void UpdateIsReadOnly()
+ {
+ Control.Editable = !Element.IsReadOnly;
+ if (Element.IsReadOnly && Control.Window?.FirstResponder == Control.CurrentEditor)
+ Control.Window?.MakeFirstResponder(null);
+ }
}
}
\ No newline at end of file
UpdateAlignment();
else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
UpdateMaxLength();
+ else if (e.PropertyName == Xamarin.Forms.InputView.IsReadOnlyProperty.PropertyName)
+ UpdateIsReadOnly();
base.OnElementPropertyChanged(sender, e);
}
UpdateFont();
UpdateAlignment();
UpdateMaxLength();
- }
+ UpdateIsReadOnly();
+ }
void TextFieldFocusChanged(object sender, BoolEventArgs e)
{
if (currentControlText.Length > Element?.MaxLength)
Control.StringValue = currentControlText.Substring(0, Element.MaxLength);
}
+
+
+ void UpdateIsReadOnly()
+ {
+ Control.Editable = !Element.IsReadOnly;
+ if (Element.IsReadOnly && Control.Window?.FirstResponder == Control.CurrentEditor)
+ Control.Window?.MakeFirstResponder(null);
+ }
}
}
\ No newline at end of file
RegisterPropertyHandler(InputView.IsSpellCheckEnabledProperty, UpdateIsSpellCheckEnabled);
RegisterPropertyHandler(Editor.PlaceholderProperty, UpdatePlaceholder);
RegisterPropertyHandler(Editor.PlaceholderColorProperty, UpdatePlaceholderColor);
+ RegisterPropertyHandler(InputView.IsReadOnlyProperty, UpdateIsReadOnly);
}
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
return null;
}
+
+ void UpdateIsReadOnly()
+ {
+ Control.IsEditable = !Element.IsReadOnly;
+ }
}
}
\ No newline at end of file
RegisterPropertyHandler(Entry.IsTextPredictionEnabledProperty, UpdateIsSpellCheckEnabled);
RegisterPropertyHandler(Specific.FontWeightProperty, UpdateFontWeight);
RegisterPropertyHandler(Entry.SelectionLengthProperty, UpdateSelectionLength);
+ RegisterPropertyHandler(InputView.IsReadOnlyProperty, UpdateIsReadOnly);
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
return Element.Text.IndexOf(selection, Math.Max(Control.CursorPosition - selection.Length, 0));
}
+
+ void UpdateIsReadOnly()
+ {
+ Control.IsEditable = !Element.IsReadOnly;
+ }
}
}
\ No newline at end of file
UpdateDetectReadingOrderFromContent();
UpdatePlaceholderText();
UpdatePlaceholderColor();
+ UpdateIsReadOnly();
}
base.OnElementChanged(e);
UpdatePlaceholderText();
else if (e.PropertyName == Editor.PlaceholderColorProperty.PropertyName)
UpdatePlaceholderColor();
+ else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+ UpdateIsReadOnly();
}
void OnLostFocus(object sender, RoutedEventArgs e)
}
}
}
+
+ void UpdateIsReadOnly()
+ {
+ Control.IsReadOnly = Element.IsReadOnly;
+ }
}
}
\ No newline at end of file
UpdateMaxLength();
UpdateDetectReadingOrderFromContent();
UpdateReturnType();
+ UpdateIsReadOnly();
UpdateInputScope();
if (_cursorPositionChangePending)
UpdateCursorPosition();
else if (e.PropertyName == Entry.SelectionLengthProperty.PropertyName)
UpdateSelectionLength();
+ else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+ UpdateIsReadOnly();
}
protected override void UpdateBackgroundColor()
_nativeSelectionIsUpdating = false;
}
}
+
+ void UpdateIsReadOnly()
+ {
+ Control.IsReadOnly = Element.IsReadOnly;
+ }
}
}
\ No newline at end of file
UpdateTextColor();
UpdateFont();
UpdateMaxLength();
+ UpdateIsReadOnly();
}
base.OnElementChanged(e);
UpdateFont();
else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
UpdateMaxLength();
+ else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+ UpdateIsReadOnly();
}
void NativeOnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs textChangedEventArgs)
_isDisposed = true;
base.Dispose(disposing);
}
+
+ void UpdateIsReadOnly()
+ {
+ Control.IsReadOnly = Element.IsReadOnly;
+ }
}
}
\ No newline at end of file
UpdateAlignment();
UpdatePlaceholderColor();
UpdateMaxLength();
+ UpdateIsReadOnly();
}
base.OnElementChanged(e);
UpdatePlaceholderColor();
else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
UpdateMaxLength();
+ else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+ UpdateIsReadOnly();
}
internal override void OnModelFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
_isDisposed = true;
base.Dispose(disposing);
}
+
+ void UpdateIsReadOnly()
+ {
+ Control.IsReadOnly = Element.IsReadOnly;
+ }
}
}
UpdateTextAlignment();
UpdateMaxLength();
UpdateAutoSizeOption();
+ UpdateReadOnly();
+ UpdateUserInteraction();
}
private void UpdateAutoSizeOption()
UpdateKeyboard();
else if (e.PropertyName == Editor.IsTextPredictionEnabledProperty.PropertyName)
UpdateKeyboard();
- else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
- UpdateEditable();
+ else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName || e.PropertyName == Xamarin.Forms.InputView.IsReadOnlyProperty.PropertyName)
+ UpdateUserInteraction();
else if (e.PropertyName == Editor.TextColorProperty.PropertyName)
UpdateTextColor();
else if (e.PropertyName == Editor.FontAttributesProperty.PropertyName)
return newLength <= Element.MaxLength;
}
+ void UpdateReadOnly()
+ {
+ Control.UserInteractionEnabled = !Element.IsReadOnly;
+ }
+
+ void UpdateUserInteraction()
+ {
+ if (Element.IsEnabled && Element.IsReadOnly)
+ UpdateReadOnly();
+ else
+ UpdateEditable();
+ }
+
internal class FormsUITextView : UITextView
{
public event EventHandler ContentSizeChanged;
UpdateCursorSelection();
UpdateCursorColor();
+ UpdateIsReadOnly();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
UpdateCursorSelection();
else if (e.PropertyName == Specifics.CursorColorProperty.PropertyName)
UpdateCursorColor();
+ else if (e.PropertyName == Xamarin.Forms.InputView.IsReadOnlyProperty.PropertyName)
+ UpdateIsReadOnly();
base.OnElementPropertyChanged(sender, e);
}
_nativeSelectionIsUpdating = false;
}
}
- }
+
+ void UpdateIsReadOnly()
+ {
+ Control.UserInteractionEnabled = !Element.IsReadOnly;
+ }
+ }
}