когда я получаю данные от клиента tcp, я не могу вносить изменения со страниц xaml из ViewModels - PullRequest
0 голосов
/ 26 июня 2018

Я изучаю xamarin.forms и wpf. Я застрял здесь:

У меня есть tcp-сервер в моем приложении, когда мой tcp-сервер получил данные от клиентов, мое событие (которое находится в ViewModelBase) является триггером, и тогда оно должно показывать данные на текущей странице xaml, но не показывать. Кто-нибудь знает, как мне связать это событие с текущей страницей xaml.

Я хочу, чтобы, когда клиент Tcp отправлял мне данные (это просто строка), я хотел показывать эти данные на экране с помощью DisplayAlert.

Если я использую кнопку, она работает, но не хочу.

ViewModelBase Class

public class ViewModelBase : BindableBase, INavigationAware, IDestructible
{
    protected INavigationService NavigationService { get; private set; }
    protected IPageDialogService DialogService { get; private set; }

    public static ProxyServer Client { get; set; }
    public ObservableCollection<Item> ListItems { get; set; }

    private DelegateCommand _eventCommand;
    public DelegateCommand EventCommand
    {
        get { return _eventCommand; }
        set { SetProperty(ref _eventCommand, value); }
    }
    public DelegateCommand DisconnectCommand { get; set; }

    private object _lockObj = new object();

    public ViewModelBase(INavigationService navigationService,IPageDialogService dialogService)
    {
        Client = ProxyServer.GetInstance();

        EventCommand = new DelegateCommand(Client_ListenServer, () => { return true; });
        DisconnectCommand = new DelegateCommand(Disconnect, () => { return true; });

        NavigationService = navigationService;
        DialogService = dialogService;
        ListItems = new ObservableCollection<Item>()
        {
            new Item()
            {
                Id = "0",
                Name = "Android",
                Description = "Android Mobil"
            },
            new Item()
            {
                Id = "1",
                Name = "IOS",
                Description = "IOS Mobil"
            },
              new Item()
            {
                Id = "2",
                Name = "UWP",
                Description = "UWP Mobil + From"
            }
        }; // sample
    }

    private void Client_ListenServer()
    {
        Debug.WriteLine("I'm triggered");
        DialogService.DisplayAlertAsync("test title", "message", "OK !", "cancel");
    }

    private void Disconnect()
    {
        Client.Disconnect();
        RemoveEventHandler();
        DialogService.DisplayAlertAsync("Status", "Disconnected..", "OK");
    }

    #region NavigationMethods
    public virtual void OnNavigatedFrom(NavigationParameters parameters)
    {
        RemoveEventHandler();
    }
    public virtual void OnNavigatedTo(NavigationParameters parameters)
    {
        if (Client.ConnectedStatus())
            AddEventHandler();
    }
    public virtual void OnNavigatingTo(NavigationParameters parameters) 
    {
        RemoveEventHandler();
    }

    public virtual void Destroy()
    {

    }
    #endregion

    private void Client_ListenServer(object sender, EventArgs e)
    {
        Client_ListenServer(); // this method must show dialogAlert on current page
    }

    public void RemoveEventHandler()
    {
        Client.ListenServer -= Client_ListenServer;
    }
    public void AddEventHandler()
    {
        Client.ListenServer += Client_ListenServer;
    }
}

Триггер метода Client_ListenServer, но DisplayAlert не работает.

текущая страница xaml.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="DataViewer.Views.Login"
             Title="{Binding Title}">
    <ContentPage.Content>
        <StackLayout VerticalOptions="CenterAndExpand" Spacing="20" Padding="20"> 
            <Entry  Text="{Binding Username}" Placeholder="Username"/>
            <Entry Text="{Binding Password}" Placeholder="Password" IsPassword="true"/>
            <Button Text="Login" VerticalOptions="CenterAndExpand" Command="{Binding AuthorizeCommand}"/>

        </StackLayout>
    </ContentPage.Content>
    <ContentPage.ToolbarItems>
        <ToolbarItem Name="MenuItem1" Order="Secondary" Text="Connect" Command="{Binding ConnectCommand}"/>
        <ToolbarItem Name="MenuItem2" Order="Secondary" Text="Disconnect" Command="{Binding DisconnectCommand}" />
        <ToolbarItem Name="MenuItem2" Order="Secondary" Text="Get Data" Command="{Binding EventCommand}" />
    </ContentPage.ToolbarItems>
</ContentPage>

my app.cs

public partial class App : PrismApplication
    {
        public App() : this(null) { }

        public App(IPlatformInitializer initializer) : base(initializer) { }

        protected override async void OnInitialized()
        {
            InitializeComponent();
            await NavigationService.NavigateAsync("NavigationPage/ConnectionPage");
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<NavigationPage>();
            containerRegistry.RegisterForNavigation<Login, LoginViewModel>();
            containerRegistry.RegisterForNavigation<Views.ListView, ListViewModel>();
            containerRegistry.RegisterForNavigation<Item, ItemViewModel>();
            containerRegistry.RegisterForNavigation<ConnectionPage>();
        }
    }

Android mainActivity Class

  [Activity(Label = "DataViewer", Icon = "@mipmap/ic_launcher", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(bundle);
            UserDialogs.Init(this);
            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App(new AndroidInitializer()));
        }

    }

    public class AndroidInitializer : IPlatformInitializer
    {
        public void RegisterTypes(IContainerRegistry container)
        {
            // Register any platform specific implementations
        }
    }

1 Ответ

0 голосов
/ 26 июня 2018

Вам нужно использовать

Device.BeginInvokeOnMainThread( () => {
  // whatever UI operation you need goes here
});

чтобы заставить ваш код пользовательского интерфейса выполняться в основном потоке из фонового потока

...