简体   繁体   中英

Set binding from code dont work in xamarin.forms app

Im trying to use accordion in my xamarin.forms app.I can use it without any problems But when I want to use this with viewmodels.No data is shown in accordion .My viewmodel is like this ;

 namespace xamarinapp
{
   public class TestViewModel : ViewModelBase
    {
        private readonly IServiceWrapper _myServiceWrapper;
        private readonly IAuthenticationService _authenticationService;

        public string viemodelName { get; set; }

        private bool UserLogCheck = false;
        private ObservableRangeCollection<dataInfro> _Acclist;
        public ObservableRangeCollection<Models.dataInfro> Acclist
        {
            get
            {
                return _Acclist;
            }
            set
            {
                _Acclist = value;
                 RaisePropertyChanged(() => Acclist);
            }
        }

        public override async Task InitializeAsync(object navigationData)
        {
            UserLogCheck = DependencyService.Get<LoginInterface>().LoginExists();
            if (!UserLogCheck)
            {
                NavigationService.NavigateToAsync<LoginViewModel>();
            }
            else
            {
              await  getData();
            }
        }
        public ICommand ItemSelectedCommand2 => new Command<dataInfro>(OntaptedItem);
        private async void OntaptedItem(dataInfro item)
        {

            await NavigationService.NavigateToAsync<OgrenciNotViewModel>(item.ogrId.ToString());

        }
        public TestViewModel(IServiceWrapper myServiceWrapper)
        {
            _myServiceWrapper = myServiceWrapper;
            _Acclist = new ObservableRangeCollection<dataInfro>();

        }
        private async Task getData()
        {
            ServiceWrapper serviceWrapper = new ServiceWrapper();
            var loginUser = DependencyService.Get<LoginInterface>().getAccount();
            var data =  await _myServiceWrapper.GetDataSecure<Ogrencilik>("GetDataUrl", loginUser);
            Acclist =new ObservableRangeCollection<dataInfro>(data.dataCollect);
        }
    }

}

And the accordion custom control is like this.(from https://kimsereyblog.blogspot.com.tr/2016/10/build-accordion-view-in-xamarinforms.html )

namespace xamarinapp
{
    public class DefaultTemplate : AbsoluteLayout
    {
        public DefaultTemplate()
        {
            this.Padding = 0;
            this.HeightRequest = 50;
            var title = new Label { HorizontalTextAlignment = TextAlignment.Start, HorizontalOptions = LayoutOptions.StartAndExpand };
            var price = new Label { HorizontalTextAlignment = TextAlignment.End, HorizontalOptions = LayoutOptions.End };
            this.Children.Add(title, new Rectangle(0, 0.5, 0.5, 1), AbsoluteLayoutFlags.All);
            this.Children.Add(price, new Rectangle(1, 0.5, 0.5, 1), AbsoluteLayoutFlags.All);
            title.SetBinding(Label.TextProperty, "name", stringFormat: "{0:c1}");
            price.SetBinding(Label.TextProperty, "balance", stringFormat: "{0:C2}");
        }
    }

    public class AccordionView : ScrollView
    {
        private StackLayout _layout = new StackLayout { Spacing = 1 };

        public DataTemplate Template { get; set; }
        public DataTemplate SubTemplate { get; set; }

        public static readonly BindableProperty ItemsSourceProperty =
            BindableProperty.Create(
                propertyName: "ItemsSource",
                returnType: typeof(IList),
                declaringType: typeof(AccordionSectionView),
                defaultValue: default(IList),
                propertyChanged: AccordionView.PopulateList);

        public IList ItemsSource
        {
            get { return (IList)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        public AccordionView()
        {
            var itemTemplate = new DataTemplate(typeof(DefaultTemplate));
            this.SubTemplate = itemTemplate;
            this.Template = new DataTemplate(() => (object)(new AccordionSectionView(itemTemplate, this)));
            this.Content = _layout;
        }

        void PopulateList()
        {
            _layout.Children.Clear();

            foreach (object item in this.ItemsSource)
            {
                var template = (View)this.Template.CreateContent();
                template.BindingContext = item;
                _layout.Children.Add(template);
            }
        }

        static void PopulateList(BindableObject bindable, object oldValue, object newValue)
        {
            if (oldValue == newValue) return;
            ((AccordionView)bindable).PopulateList();
        }
    }

    public class AccordionSectionView : StackLayout
    {
        private bool _isExpanded = false;
        private StackLayout _content = new StackLayout { HeightRequest = 0 };
        private Color _headerColor = Color.FromHex("0067B7");
        private ImageSource _arrowRight = ImageSource.FromFile("ic_keyboard_arrow_right_white_24dp.png");
        private ImageSource _arrowDown = ImageSource.FromFile("ic_keyboard_arrow_down_white_24dp.png");
        private AbsoluteLayout _header = new AbsoluteLayout();
        private Image _headerIcon = new Image { VerticalOptions = LayoutOptions.Center };
        private Label _headerTitle = new Label { TextColor = Color.White, VerticalTextAlignment = TextAlignment.Center, HeightRequest = 50 };
        private DataTemplate _template;

        public static readonly BindableProperty ItemsSourceProperty =
            BindableProperty.Create(
                propertyName: "ItemsSource",
                returnType: typeof(IList),
                declaringType: typeof(AccordionSectionView),
                defaultValue: default(IList),
                propertyChanged: AccordionSectionView.PopulateList);

        public IList ItemsSource
        {
            get { return (IList)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        public static readonly BindableProperty TitleProperty =
            BindableProperty.Create(
                propertyName: "Title",
                returnType: typeof(string),
                declaringType: typeof(AccordionSectionView),
                propertyChanged: AccordionSectionView.ChangeTitle);

        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        public AccordionSectionView(DataTemplate itemTemplate, ScrollView parent)
        {
            _template = itemTemplate;
            _headerTitle.BackgroundColor = _headerColor;
            _headerIcon.Source = _arrowRight;
            _header.BackgroundColor = _headerColor;

            _header.Children.Add(_headerIcon, new Rectangle(0, 1, .1, 1), AbsoluteLayoutFlags.All);
            _header.Children.Add(_headerTitle, new Rectangle(1, 1, .9, 1), AbsoluteLayoutFlags.All);

            this.Spacing = 0;
            this.Children.Add(_header);
            this.Children.Add(_content);

            _header.GestureRecognizers.Add(
                new TapGestureRecognizer
                {
                    Command = new Command(async () =>
                    {
                        if (_isExpanded)
                        {
                            _headerIcon.Source = _arrowRight;
                            _content.HeightRequest = 0;
                            _content.IsVisible = false;
                            _isExpanded = false;
                        }
                        else
                        {
                            _headerIcon.Source = _arrowDown;
                            _content.HeightRequest = _content.Children.Count * 50;
                            _content.IsVisible = true;
                            _isExpanded = true;

                            // Scroll top by the current Y position of the section
                            if (parent.Parent is VisualElement)
                            {
                                await parent.ScrollToAsync(0, this.Y, true);
                            }
                        }
                    })
                }
            );
        }

        void ChangeTitle()
        {
            _headerTitle.Text = this.Title;
        }

        void PopulateList()
        {
            _content.Children.Clear();

            foreach (object item in this.ItemsSource)
            {
                var template = (View)_template.CreateContent();
                template.BindingContext = item;
                _content.Children.Add(template);
            }
        }

        static void ChangeTitle(BindableObject bindable, object oldValue, object newValue)
        {
            if (oldValue == newValue) return;
            ((AccordionSectionView)bindable).ChangeTitle();
        }

        static void PopulateList(BindableObject bindable, object oldValue, object newValue)
        {
            if (oldValue == newValue) return;
            ((AccordionSectionView)bindable).PopulateList();
        }
    }
}

And I'm trying to set binding like this

 [XamlCompilation(XamlCompilationOptions.Skip)]
    public partial class PageOgrenciNotModal : ContentPage
    {
        public PageOgrenciNotModal()
        {
            InitializeComponent();
        }
        protected override void OnBindingContextChanged()
        {
            base.OnBindingContextChanged();
            Accorview.SetBinding(AccordionView.ItemsSourceProperty, "Acclist");
            Accorview.Template.SetBinding(AccordionSectionView.TitleProperty, "Title");
            Accorview.Template.SetBinding(AccordionSectionView.ItemsSourceProperty, "List");
        }
    }

But nothing is happen.(note:there is no problem in getting data ,I can use same approach with listview with no problems).Any help is appreciated ,thanks

If you are not using a MVVM Framework you have to set the BindingContext of the page yourself.

So do something like:

public PageOgrenciNotModal()
{
    InitializeComponent();
    BindingContext = new TestViewModel();

}

this

Accorview.SetBinding(ListView.ItemsSourceProperty, "Accorlist");

looks suspicious.

IMHO, it should be

Accorview.SetBinding(AccordionView.ItemsSourceProperty, "Accorlist");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM