当我从 tcp 客户端接收数据时,我无法从 ViewModels 的 xaml 页面进行更改
when I receive data from tcp client, I cannot make changes from xaml pages from ViewModels
我正在学习 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>
我的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
}
}
您需要使用
Device.BeginInvokeOnMainThread( () => {
// whatever UI operation you need goes here
});
强制您的 UI 代码从后台线程在主 (UI) 线程上执行
我正在学习 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>
我的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
}
}
您需要使用
Device.BeginInvokeOnMainThread( () => {
// whatever UI operation you need goes here
});
强制您的 UI 代码从后台线程在主 (UI) 线程上执行