Quantcast
Channel: Xamarin.Forms — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 75885

ViewCell reusing issue?

$
0
0

Hi,

I have a problem with a custom ViewCell, I guess it has to do with reusing cells/renderers but I can't figure out how to handle this correctly. Here is the implementation of my custom ViewCell which I use to display all kind of controls in a TableViewwhich is used as a Form. Some forms have more than 30 fields to edit. Sorry for the german summarys.

    /// Zelle welche in TableView Forms verwendet wird. Stellt ein Label mit einem Control da.
    /// </summary>
    public class CustomControlViewCell : CustomViewCell 
    {
        private readonly Grid _gridLayout;
        private readonly Label _label;

        /// <summary>
        /// Name der <c>Control</c> Property
        /// </summary>
        public const string ControlPropertyName = "Control";
        /// <summary>
        /// Die BindableProperty
        /// </summary>
        public static readonly BindableProperty ControlProperty = BindableProperty.Create<CustomControlViewCell, View>(i => i.Control, null, BindingMode.TwoWay, null, ControlChanged);
        /// <summary>
        /// Das Control der <c>ControlViewCell</c>
        /// </summary>
        public View Control
        {
            get
            {
                return (View)this.GetValue(ControlProperty);
            }
            set
            {
                this.SetValue(ControlProperty, value);
            }
        }               
        /// <summary>
        /// Name der <c>Text</c> Property
        /// </summary>
        public const string TextPropertyName = "Text";
        /// <summary>
        /// Die BindableProperty
        /// </summary>
        public static readonly BindableProperty TextProperty = BindableProperty.Create<CustomControlViewCell, string>(i => i.Text, default(string), BindingMode.TwoWay, null, TextChanged);
        /// <summary>
        /// Text der vor dem Control angezeigt wird
        /// </summary>
        public string Text
        {
            get
            {
                return (string)this.GetValue(TextProperty);
            }
            set
            {
                this.SetValue(TextProperty, value);
            }
        }
        /// <summary>
        /// Erstellt eine neue Instanz von <c>CustomControlViewCell</c>
        /// </summary>
        public CustomControlViewCell()
        {
            this._label = new Label 
            {
                XAlign = TextAlignment.Start,
                VerticalOptions = LayoutOptions.CenterAndExpand,
                TextColor = Color.Gray,
                LineBreakMode = LineBreakMode.TailTruncation,
                FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label))
            };
            this._gridLayout = new Grid
            {
                HorizontalOptions = LayoutOptions.Fill,
                RowDefinitions = 
                {
                    new RowDefinition
                    {
                        Height = new GridLength(1, GridUnitType.Star)
                    }
                },
                ColumnDefinitions = 
                {
                    new ColumnDefinition
                    {
                        Width = new GridLength(1, GridUnitType.Star)
                    },
                    new ColumnDefinition
                    {
                        Width = new GridLength(2, GridUnitType.Star)
                    }
                }
            };
            this._gridLayout.Children.Add(
                new ContentView
                {
                    Padding = new Thickness(5, 0, 5, 0),
                    Content = this._label
                }, 0, 0);

            this.Content = this._gridLayout;

        }
        /// <summary>
        /// Wird gefeuert wenn sich der Text ändert
        /// </summary>
        /// <param name="obj">Die Zelle</param>
        /// <param name="oldValue">Alter Wert</param>
        /// <param name="newValue">Neuer Wert</param>
        private static void TextChanged(BindableObject obj, string oldValue, string newValue)
        {
            var cell = obj as CustomControlViewCell;

            if (cell != null)
            {
                cell._label.Text = newValue;
            }
        }
        /// <summary>
        /// Wird gefeuerlt wenn das <c>Control</c> sich ändert
        /// </summary>
        /// <param name="obj">Die Zelle</param>
        /// <param name="oldValue">Alter Wert</param>
        /// <param name="newValue">Neuer Wert</param>
        private static void ControlChanged(BindableObject obj, View oldValue, View newValue)
        {
            var cell = obj as CustomControlViewCell;

            if (cell != null)
            {
                if (oldValue != null)
                {
                    cell._gridLayout.Children.Remove(oldValue);
                }
                if (newValue != null)
                {
                    newValue.VerticalOptions = LayoutOptions.CenterAndExpand;
                    cell._gridLayout.Children.Add(newValue, 1, 0);
                }
            }
        }
        /// <summary>
        /// Wenn kein Kommando gesetzt Focus auf Control setzen
        /// </summary>
        protected override void OnTapped()
        {
            base.OnTapped();

            if (this.Command == null)
            {
                this.Control.Focus();
            }
        }
    }

Here is a snippet how I use it:

<local:CustomControlViewCell Text="Kaufdatum">
    <local:CustomControlViewCell.Control>
      <local:CustomDatePicker
        NullableDate="{Binding Kaufdatum}"
        IsEnabled="{Binding Source={x:Reference ContentPage}, Path=BindingContext.ReadOnly, Converter={StaticResource FwInverseBoolConverter}}" />
    </local:CustomControlViewCell.Control>
    </local:CustomControlViewCell>

    <local:CustomControlViewCell Text="Kaufpreis">
    <local:CustomControlViewCell.Control>
      <local:CustomEntry
        Text="{Binding Kaufpreis, Converter={StaticResource FwNullableDoubleConverter}}"
        Keyboard="Numeric"
        IsEnabled="{Binding Source={x:Reference ContentPage}, Path=BindingContext.ReadOnly, Converter={StaticResource FwInverseBoolConverter}}" />
    </local:CustomControlViewCell.Control>
</local:CustomControlViewCell>

When I have a lot of cells and start scrolling it seems that some other cells randomly get properties from other cells. For example an Entrywhich contains just text gets the Numeric Keyboard, event though this is never set. Same goes for other properties too, like IsEnabled.


Viewing all articles
Browse latest Browse all 75885

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>