Xamarin Forms -> Activity Indicator не работает, если команды операторов должны быть выполнены - PullRequest
0 голосов
/ 06 сентября 2018

Использование Visual Studio 2017 Community 15.8.1

Это после прохождения всех параметров stackoverflow, касающихся ActivityIndicator.Так что, хотя это может быть дублирование, но ничто не поможет мне.Поэтому, наконец, решил опубликовать мои тренировки и получить лучшую помощь отсюда.

Что я пробовал до сих пор: -
1. {Binding IsLoading} + INotifyPropertyChanged + public void RaisePropertyChanged (строка propName) + IsLoading = true;concept.
2. ActivityIndicator_Busy.IsVisible = false;(Доступ к прямому управлению)

Эти два подхода были в основном рекомендованы, и я углубился в каждый из них, так как много часов за последние несколько недель.Но ничего не сломалось.

Чего я достиг?: -
ActivityIndicator_Busy.IsVisible = false;концепция работает гладко только тогда, когда я ставлю return перед выполнением операторов (для целей тестирования);заявление о событии «Нажатие кнопки».(Прикрепленное изображение) Но как только уберу возврат;При нажатии кнопки, сразу после некоторой паузы, открывается домашняя страница.

МОЙ Вопрос: -
1. Это характерно для текущего сценария, как запустить ActivityIndicator Немедленно, когда пользовательнажимает кнопку приветствия.
2. Что касается того же, при запуске приложения также появляется пустой белый экран на несколько секунд, почти 30 секунд, который я также хочу показать ActivityIndicator.Но не знаю, как навязать эту логику в каком экземпляре.

Мои входы

Мой файл MainPage.xaml: - (Отредактировано06 сентября 2018 09.11)

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage x:Name="page_main_page"
             NavigationPage.HasBackButton="False"
             NavigationPage.HasNavigationBar="False"
             xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:appNutri"
             BindingContext="{x:Reference page_main_page}"
             x:Class="appNutri.MainPage">
    <ContentPage.Content>
        <StackLayout BackgroundColor="White" 
                     HorizontalOptions="FillAndExpand" 
                     VerticalOptions="FillAndExpand">
            <StackLayout>
                <Image x:Name="Image_Welcome" 
                       Source="welcome.png" 
                       HorizontalOptions="CenterAndExpand" 
                       VerticalOptions="CenterAndExpand"
                       WidthRequest="300" 
                       HeightRequest="300" />
                <Button x:Name="Button_Welcome" 
                        Clicked="Button_Welcome_Clicked" 
                        Text="Welcome!" 
                        BackgroundColor="DeepSkyBlue" 
                        HorizontalOptions="CenterAndExpand" 
                        VerticalOptions="CenterAndExpand"
                        TextColor="White" 
                        HeightRequest="60" />
            </StackLayout>
            <StackLayout BackgroundColor="White" 
                         HorizontalOptions="FillAndExpand" 
                         VerticalOptions="FillAndExpand">
                <ActivityIndicator 
                        x:Name="ActivityIndicator_Busy"
                        Color="Black"
                        IsEnabled="True" 
                        HorizontalOptions="Center" 
                        VerticalOptions="Center"
                        IsRunning="{Binding Source={x:Reference page_main_page}, Path=IsLoading}" 
                        IsVisible="{Binding Source={x:Reference page_main_page}, Path=IsLoading}" />
            </StackLayout>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

My MainPage.cs Код: -
(отредактировано 06 сентября 2018 13.13)

using appNutri.Model;
using SQLite;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace appNutri
{
    public partial class MainPage : Xamarin.Forms.ContentPage, INotifyPropertyChanged 
    {

        private bool isLoading;

        public bool IsLoading
        {
            get
            {
                return isLoading;
            }

            set
            {
                isLoading = value;
                RaisePropertyChanged("IsLoading");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propName)
        {           
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));

            }
        }

        public MainPage()
        {
            InitializeComponent();
            BindingContext = this;
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            BindingContext = this;
        }

        protected async void Button_Welcome_Clicked(object sender, EventArgs e)
        {
            IsLoading = true;

            await Select_Local_User_Information();

            IsLoading = false;
        }

        private async Task Select_Local_User_Information()
        {

            IsLoading = true;

            string where_clause = "";

            try
            {
                Sql_Common.Database_Folder_Path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);

                string Database_Full_Path = Path.Combine(Sql_Common.Database_Folder_Path, Sql_Common.Database_Name);

                SQLiteConnection connection = new SQLiteConnection(Database_Full_Path);

                //connection.DropTable<User_Master>();
                //connection.Delete(connection.Table<User_Master>());
                //connection.CreateTable<User_Master>(CreateFlags.ImplicitPK | CreateFlags.AutoIncPK);

                connection.CreateTable<User_Master>();

                int count = connection.ExecuteScalar<int>("Select count(*) from User_Master");

                if (count == 0)
                {
                    connection.DropTable<User_Master>();
                    connection.CreateTable<User_Master>();

                    //IsLoading = false;
                    //IsBusy = false;

                    await Navigation.PushAsync(new User_Register_Page());

                }
                else
                {
                    Sql_Common.User_Logged = true;

                    var Local_User_Data = connection.Table<User_Master>().ToList();

                    User_Master.Logged_User_Details_Container.First_Name = Local_User_Data[0].First_Name;
                    User_Master.Logged_User_Details_Container.Cell1 = Local_User_Data[0].Cell1;

                    where_clause = " Upper ( First_Name ) = " + "'" + User_Master.Logged_User_Details_Container.First_Name.ToUpper().Trim() + "'" + " and " +
                                   " Cell1 = " + "'" + User_Master.Logged_User_Details_Container.Cell1.Trim() + "'";

                    int records = Sql_Common.Get_Number_Of_Rows_Count("User_Master", where_clause);

                    if (records == 0)
                    {
                        connection.DropTable<User_Master>();
                        connection.CreateTable<User_Master>();

                        IsLoading = false;

                        await Navigation.PushAsync(new User_Register_Page());

                    }
                    else
                    {
                        User_Master.User_Master_Table(where_clause, User_Master.Logged_User_Details_Container);

                        IsLoading = false;

                        await Navigation.PushAsync(new User_Home_Page());

                    }

                }

                connection.Close();
            }
            catch (SQLiteException ex)
            {
                string ex_msg = ex.Message;
            }

            IsLoading = false;
        }
    }
}

Working Image


04-октябрь-2018
Окончательно решено с помощью Этот ответ


1 Ответ

0 голосов
/ 06 сентября 2018

Обновление 2018-09-10

Вы думаете, что реализовали INotifyPropertyChanged, добавив INotifyPropertyChanged к определению вашего класса и добавив событие

public event PropertyChangedEventHandler PropertyChanged;

вместе с вызовом события

public void RaisePropertyChanged(string propName)
{           
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}

Во всяком случае, поскольку ContentPage уже реализует INotifyPropertyChanged, добавление тех, которые не реализуют INotifyPropertyChanged. ContentPage уже определяет событие (точнее, BindableObject, от которого ContentPage косвенно наследуется). Любой объект, который полагается на получение информации об изменениях свойств на вашей странице, подпишется на событие PropertyChanged предка, а не на определенное вами событие PropertyChanged, поэтому ActivityIndicator не будет обновляться.

Просто удалите событие, которое вы определили, и наберите OnPropertyChanged вместо RaisePropertyChanged(), и все будет в порядке.

private bool isLoading;

public bool IsLoading
{
    get
    {
        return isLoading;
    }

    set
    {
        isLoading = value;
        OnPropertyChanged();
    }
}

Поскольку OnPropertyChanged объявлено как

protected void OnPropertyChanged([CallerMemberName] string propertyName = null)

вам не нужно передавать имя свойства вручную. Компилятор сделает это за вас, так как CallerMemberNameAttribute.

Конец обновления

Расширение XAML {Binding IsLoading} связывает ActivityIndicator с BindingContext вашей страницы. По умолчанию BindingContext равен null, поэтому с ним нечего связывать, и все ваши усилия напрасны.

с моделью представления

Предпочтительным решением будет использование модели представления и присвоение ей MainPage.BindingContext, например,

var page = new MainPage()
{
    BindingContext = new MainPageViewModel()
}

но если вы идете по этому пути, вы должны переместить всю свою логику пользовательского интерфейса в эту модель представления и инкапсулировать ваш SQL-доступ и бизнес-логику в другие классы, чтобы сохранить модель представления в чистоте от доступа к ресурсам и бизнес-логики , Наличие доступа к ресурсам и логики в коде может сработать для этого небольшого примера, но, скорее всего, станет неразрешимым беспорядком.

без модели представления

В любом случае, у вас нет , чтобы использовать модель представления для использования привязок. Вы можете установить BindingContext для страницы (или некоторых детей) или использовать Source из BindingExtension

Настройка BindingContext

BindingContext передается с любой страницы или представления его детям. Сначала вы должны дать своей странице имя с x:Name="Page" (не обязательно использовать Page, во всяком случае, вы не можете использовать имя класса своей страницы) и установить BindingContext для этой страницы

<ContentPage ...
    x:Name="Page"
    BindingContext="{x:Reference Page}"
    ...>

теперь привязка к IsLoading должна работать.

Использование Source в Binding

Если вы хотите сослаться на что-то другое, чем BindingContext представления, BindingExtension имеет свойство Source. Вы также должны дать название своей странице (см. Выше)

<ContentPage ...
    x:Name="Page"
    ...>

и теперь вы можете ссылаться на это в вашей привязке

<ActivityIndicator 
    ...
    IsRunning="{Binding Path=IsLoading, Source={x:Reference Page}}" 
    IsVisible="{Binding Path=IsLoading, Source={x:Reference Page}}"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...