Quantcast
Channel: Recent Threads — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 204402

Setting an elements visibility within a composite control

$
0
0

Hi All,

I'm not quite sure where I'm going wrong here, I'm sure its data binding related, but basically I'm trying to build an autocomplete entry. I have an entry which when the user starts to type a list view below would be displayed of suggestions. This part works great, however I want to hide the listview when the suggestion is clicked or the entry isn't being typed into. This part I'm struggling with. I've tried using a grid (I was using a stack layout before) and setting the rows height to zero, I've tried directly setting the ListViews visibility in the code behind and I've tried binding the controls visibility to a property.

Do you have to implement INotifyProperty changed here?

XAML

<ContentView 
             xmlns:behaviors="clr-FB.Behaviors;assembly=FB"
             x:Class="FB.Controls.MyControl2"
             x:Name="This">

    <ContentView.Content>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition Height="70"/>
            </Grid.RowDefinitions>
            <Entry x:Name="innerEntry" 
                   Grid.Row="0" FontFamily="{StaticResource Key='AbrilFatface'}">
                    <Entry.Behaviors>
                        <behaviors:EventToCommandBehavior EventName="TextChanged" 
                                                          Command="{Binding EntryTextChanged, Source={Reference This}}" />
                    </Entry.Behaviors>
            </Entry>
             <ListView x:Name="innerSuggestionBox" RowHeight="25"
                        Grid.Row="1"
                            IsVisible="{Binding IsEntryVisible, Source={Reference This}}"
                            behaviors:ItemTappedCommandListView.ItemTappedCommand="{Binding SuggestionItemTapped, Source={Reference This}}">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <ViewCell>
                                    <ViewCell.View>
                                        <StackLayout Orientation="Horizontal">
                                            <Label Text="{Binding .}" HorizontalOptions="Start" />
                                        </StackLayout>
                                    </ViewCell.View>
                                </ViewCell>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                </ListView>
        </Grid>
   </ContentView.Content>
</ContentView>

Code Behind

namespace FB.Controls
{
    public partial class MyControl2 : ContentView
    {
        public MyControl2()
        {
            InitializeComponent();

            privateSuggestionList = new ObservableRangeCollection<string>();

            this.IsEntryVisible = false;
            ListHeight = 0;
            innerEntry.SetBinding(Entry.PlaceholderProperty, new Binding("Placeholder", source: this));
            innerEntry.SetBinding(Entry.TextProperty, new Binding("Text", source: this));
            innerSuggestionBox.SetBinding(ListView.ItemsSourceProperty, new Binding("privateSuggestionList", source: this));

            innerEntry.Keyboard = Keyboard.Create(KeyboardFlags.CapitalizeSentence | KeyboardFlags.Spellcheck);
            //innerSuggestionBox.IsVisible = false;
            //innerSuggestionBox.SetBinding(ListView.IsVisibleProperty, new Binding("IsEntryVisible", source: this));
        }



        public static BindableProperty PlaceholderProperty =
            BindableProperty.Create("Placeholder", typeof(string), typeof(MyControl2), default(string));

        public string Placeholder
        {
            // ----- The display text for the composite control.
            get { return (string)base.GetValue(PlaceholderProperty); }
            set
            {
                if (value != this.Placeholder)
                    base.SetValue(PlaceholderProperty, value);
            }
        }

        public static BindableProperty TextProperty = BindableProperty.Create(
            propertyName: "Text",
            returnType: typeof(string),
            declaringType: typeof(MyControl2),
            defaultValue: string.Empty,
            defaultBindingMode: BindingMode.OneWay,
            propertyChanged: HandleTextPropertyChanged);

        public string Text
        {
            // ----- The display text for the composite control.
            get { return (string)base.GetValue(TextProperty); }
            set
            {
                if (value != this.Text)
                    base.SetValue(TextProperty, value);
            }
        }

        private static void HandleTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
        {
            MyControl2 targetView;

            targetView = (MyControl2)bindable;
            if (targetView != null)
                targetView.Text = (string)newValue;
            targetView.IsEntryVisible = true;
        }

        private bool _isEntryVisible;
        public bool IsEntryVisible
        {
            get { return _isEntryVisible; }
            set
            {
                _isEntryVisible = value;
                //RaisePropertyChanged(() => IsEntryVisible);
            }
        }

        private int _listHeight;
        public int ListHeight
        {
            get { return _listHeight; }
            set
            {
                _listHeight = value;
                //RaisePropertyChanged(() => IsEntryVisible);
            }
        }

        public ObservableRangeCollection<string> privateSuggestionList { get; set; }

        public ICommand SuggestionItemTapped => new Command<string>(onSuggestionTapped);

        private void onSuggestionTapped(string item)
        {
            this.Text = item;
            Debug.WriteLine("List disabled");
            //innerSuggestionBox.IsVisible = false;
            IsEntryVisible = false;
            ListHeight = 0;
            Debug.WriteLine("IsEntryVisible value: {0}", IsEntryVisible);
        }

        public ICommand EntryTextChanged => new Command(onEntryTextChanged);

        private void onEntryTextChanged()
        {
            if (this.ItemsSource2 != null)
            {
                this.privateSuggestionList.Clear();
                this.privateSuggestionList.AddRange(ItemsSource2.Cast<string>()
                               .Where(x => x.ToLower().StartsWith(this.Text.ToLower(), StringComparison.Ordinal))
                               .OrderBy(x => x)
                               .ToList());
               Debug.WriteLine("List Enabled");
               //innerSuggestionBox.IsVisible = true;
               IsEntryVisible = true;
               ListHeight = 70;
               Debug.WriteLine("IsEntryVisible value: {0}", IsEntryVisible);
            }
        }

        public ICommand EntryTextLeft => new Command(onEntryTextLeft);

        private void onEntryTextLeft()
        {
            Debug.WriteLine("List disabled");
            IsEntryVisible = false;
            ListHeight = 0;
            //innerSuggestionBox.IsVisible = false;
        }

        public static readonly BindableProperty ItemsSource2Property =
            BindableProperty.Create(nameof(ItemsSource2), typeof(IEnumerable), typeof(MyControl2), null,
                                     BindingMode.Default, null, OnItemsSource2Changed);

        public IEnumerable ItemsSource2
        {
            get { return (IEnumerable)GetValue(ItemsSource2Property); }
            set { SetValue(ItemsSource2Property, value); }
        }

        static void OnItemsSource2Changed(BindableObject bindable, object oldvalue, object newvalue)
        {
            System.Diagnostics.Debug.WriteLine("source changed");
        }

    }
}

Viewing all articles
Browse latest Browse all 204402

Trending Articles