C# xamarin广播接收机访问视图模型

C# xamarin广播接收机访问视图模型,c#,android,mvvm,xamarin,C#,Android,Mvvm,Xamarin,注释:Xamarin 4.2.1.64,Visual Studio 2015 proff 我已经创建了一个跨平台的应用程序,可以在扫描条形码的android设备上运行 当前扫描时,软件具有可选的输出模式(缓冲区、键盘、剪贴板和意图) 当前正在使用键盘模式 流量 用户单击设备按钮扫描条形码,软件尝试转储到屏幕上的输入,如果不是,则将其替换为选项卡(应用程序在启动时将焦点设置为输入字段)。当点击应用程序上的按钮时,它会调用我的服务来查询一组数据并返回结果,然后更新结果列表以供用户查看 我需要更改的流

注释:Xamarin 4.2.1.64,Visual Studio 2015 proff

我已经创建了一个跨平台的应用程序,可以在扫描条形码的android设备上运行

当前扫描时,软件具有可选的输出模式(缓冲区、键盘、剪贴板和意图)

当前正在使用键盘模式

流量

用户单击设备按钮扫描条形码,软件尝试转储到屏幕上的输入,如果不是,则将其替换为选项卡(应用程序在启动时将焦点设置为输入字段)。当点击应用程序上的按钮时,它会调用我的服务来查询一组数据并返回结果,然后更新结果列表以供用户查看

我需要更改的流量

用户单击设备按钮扫描条形码,只有这一次设备被设置为意图和广播,我的应用程序接收器接收广播,从意图中读取条形码并调用我的viewmodel以使用条形码更新字段。viewmodel现在将更改为检测字段更改并相应地运行该方法

到目前为止的代码

便携式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"
         x:Class="StockCheckApp.Views.ScannerPage"
         xmlns:ViewModels="clr-namespace:StockCheckApp.ViewModels;assembly=StockCheckApp">
  <Label Text="{Binding MainText}" VerticalOptions="Center" HorizontalOptions="Center" />

  <StackLayout Orientation="Vertical">

<Entry x:Name="myBox" Text="{Binding UserInput, Mode=TwoWay}" />
<Button Text="Check Stock" Command="{Binding PostCommand}"/>

<ListView ItemsSource="{Binding StockList}"
        HasUnevenRows="True">
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
        <StackLayout Orientation="Vertical" Padding="12,6">
          <Label Text="{Binding St_Code}" FontSize="24" />
          <Label Text="{Binding St_Desc}" />
          <Label Text="{Binding Sl_Loc}" />
          <Label Text="{Binding Sa_Datetime}" />
          <Label Text="{Binding Sa_Qty}" />
        </StackLayout>
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
便携式主视图模型

public class MainViewModel : INotifyPropertyChanged
{
    ScannerPage page;
    private List<Stock> _stockList;
    private string _userInput;
    public List<Stock> StockList
    {
        get { return _stockList; }
        set
        {
            _stockList = value;
            OnPropertyChanged();
        }
    }

    public string UserInput
    {
        get { return _userInput; }
        set
        {
            _userInput = value;
            OnPropertyChanged();
        }         
    }

    public MainViewModel(ScannerPage parent)
    {
        page = parent;
        page.MyBox.Focus();
    }

    public Command PostCommand
    {
        get
        {
            return new Command(async () =>
            {
                var stockService = new StockService();
                StockList = await stockService.GetStockAsync(UserInput);
                page.MyBox.Focus();
            });
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        //use this to clear? then reset focus?
    }
}
我被困在什么上

我一步一步地执行,代码就到达了断点,但在这个阶段,我需要我的接收器以某种方式更新输入字段

我还不熟悉Xamarin,而且我学到了很多,所以我意识到这可能是一个简单的答案

同时


我打算做的对吗?是否接收条形码编号并访问viewmodels“userinput”属性并对其进行更改?os我是否应该访问视图上的字段并对其进行更改,然后允许我的属性更改方法执行业务逻辑?

您可以使用Xamarin.Forms附带的消息中心

让您的ViewModel
订阅来自您服务的事件的MessagingCenter,然后使用该事件更新绑定到该字段的属性。如果您的PCL中需要一个类型来映射订阅,请在PCL中为您的服务创建一个不需要任何实际方法契约的接口,然后让您的服务实现它,以便您可以使用强类型设置订阅:

// in your PCL
public interface IScanReceiver
{
}

// in your android project
public class Receiver1 : BroadcastReceiver, IScanReceiver

// in your viewmodel
MessagingCenter.Subscribe<IScanReceiver>();
//在您的PCL中
公共接口IScanReceiver
{
}
//在你的android项目中
公共类接收者1:广播接收者,IScanReceiver
//在您的viewmodel中
MessagingCenter.Subscribe();
或者,您可以在依赖项服务中设置ViewModels,然后使用服务定位器(anti)模式查找ViewModel实例并更新绑定到该字段的属性。
MVVM Light:在为您提供执行此操作的工具方面做得非常好。

愚蠢的问题1,当您说PCL时,您指的是什么?您的可移植类库。假设您的XAML就在这里。如果您使用的是共享库,那么我所说的一切都是一样的。无论你的ViewModel和View在哪里,我将从Xamarin论坛上的Craig Dunn那里偷一个例子,但它应该有助于解释一下。在本例中,它使用一个活动将消息发送到Xamarin.Forms页面,但您可以使用接收方将其发送到ViewModel或页面:Ok,因此我创建了接口,添加了一个名为Result{get;set:}的属性字符串。我的接收者实现该属性,然后我说Result=decodedBarcode;这很好,但是在我的viewmodel中如何以及在哪里使用messagecenter方法呢?Craig Dunn的例子,基本上是在我的接收器中创建一个messagecenter来发送字符串,然后让我的ScannerPage类订阅消息?据我所知,如果我将字段设置为=结果,那么我的ViewModel中的OnProperty方法应该正确吗?
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new[] { "android.intent.action.bcr.newdata" })]
public class Receiver1 : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        Toast.MakeText(context, "Received intent!", ToastLength.Short).Show();
        Services.StockService meh = new Services.StockService();
        //MainViewModel md = new MainViewModel();
        Dowork(meh, intent);
    }

    //this isnt correct i need to update viewmodel not call service direct!
    private async void Dowork (Services.StockService meh, Intent intent)
    {
        string action = intent.Action.ToString();
        string decodedBarcode = intent.GetStringExtra(BCRIntents.ExtraBcrString);
        //now i just need to update my field in the xaml....somehow
    }
}
// in your PCL
public interface IScanReceiver
{
}

// in your android project
public class Receiver1 : BroadcastReceiver, IScanReceiver

// in your viewmodel
MessagingCenter.Subscribe<IScanReceiver>();