Xamarin 使用 INotifyPropertyChanged 与 Entry 和 Label 以及 MVVM 绑定
Xamarin using INotifyPropertyChanged binding with Entry and Label and MVVM
我正在通过 Android 项目的 MainActivity.cs 中的意图获取字符串。我正在使用共享项目。该字符串是一个条形码,如果扫描条形码,它会由意图更新。我想通过数据绑定在 .xaml 文件的条目或标签中显示条形码字符串。
问题是,如果我手动单击条目,条目和标签中的条形码仅更新。当意图中的字符串发生变化时,如何确保标签或条目得到更新?
代码:
MainActivity.cs:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public static MainActivity Instance;
myBroadcastReceiver receiver;
BarcodeModel barcodeModel;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
// Barcode
MainActivity.Instance = this;
receiver = new myBroadcastReceiver();
barcodeModel = new BarcodeModel();
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected override void OnResume()
{
base.OnResume();
// Register the broadcast receiver dynamically
RegisterReceiver(receiver, new IntentFilter(Resources.GetString(Resource.String.activity_intent_filter_action)));
}
protected override void OnPause()
{
base.OnPause();
UnregisterReceiver(receiver);
}
public void DisplayResult(Intent intent)
{
// Output the scanned barcode to ViewModel
barcodeModel.decodedData = intent.GetStringExtra(Resources.GetString(Resource.String.datawedge_intent_key_data));
}
}
// Broadcast receiver to receive scanned data
[BroadcastReceiver(Enabled = true)]
public class myBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
String action = intent.Action;
if (action.Equals(MainActivity.Instance.Resources.GetString(Resource.String.activity_intent_filter_action)))
{
// A barcode has been scanned
MainActivity.Instance.RunOnUiThread(() => MainActivity.Instance.DisplayResult(intent));
}
}
}
}
视图模型:
public class BarcodeModel : INotifyPropertyChanged
{
private string data;
public event PropertyChangedEventHandler PropertyChanged;
public BarcodeModel()
{
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string decodedData
{
get { return data; }
set { data = value; OnPropertyChanged(); }
}
内容页:
<Label Text="{Binding decodedData}"
HorizontalOptions="StartAndExpand"
VerticalOptions="Center"
TextColor="Accent"/>
<Entry Keyboard="Text"
Placeholder="No Object selected"
VerticalOptions="Center"
HorizontalOptions="StartAndExpand"
x:Name="eintrag"
Text="{Binding decodedData}"/>
.xaml.cs 中的 BindingContext:BindingContext = new BarcodeModel();
您在 Android 项目中更改的模型与您的 bindingContext 不同,因此它不起作用。
解决方案:
使用 messagingCenter 将模型从您的 Android 项目发送到您的共享项目并在那里更新模型:
在Android项目中,每次扫码发送消息:
public void DisplayResult(Intent intent)
{
// Output the scanned barcode to ViewModel
barcodeModel.decodedData = intent.GetStringExtra(Resources.GetString(Resource.String.datawedge_intent_key_data));
barcodeModel.decodedData = "test";
MessagingCenter.Send<object, BarcodeModel>(new object(), "barCodeScanned", barcodeModel);
}
在共享项目中,订阅该消息并更新模型:
public partial class MainPage : ContentPage
{
BarcodeModel barCodeModel;
public MainPage()
{
InitializeComponent();
barCodeModel = new BarcodeModel();
barCodeModel.decodedData = "defaultValue";
this.BindingContext = barCodeModel;
MessagingCenter.Subscribe<object, BarcodeModel>(new object(), "barCodeScanned", (sender, arg) =>
{
BarcodeModel tempbarCodeModel = arg as BarcodeModel;
barCodeModel.decodedData = tempbarCodeModel.decodedData;
});
}
}
我上传了我的测试项目here,有任何问题都可以问我。
我正在通过 Android 项目的 MainActivity.cs 中的意图获取字符串。我正在使用共享项目。该字符串是一个条形码,如果扫描条形码,它会由意图更新。我想通过数据绑定在 .xaml 文件的条目或标签中显示条形码字符串。
问题是,如果我手动单击条目,条目和标签中的条形码仅更新。当意图中的字符串发生变化时,如何确保标签或条目得到更新?
代码:
MainActivity.cs:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public static MainActivity Instance;
myBroadcastReceiver receiver;
BarcodeModel barcodeModel;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
// Barcode
MainActivity.Instance = this;
receiver = new myBroadcastReceiver();
barcodeModel = new BarcodeModel();
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected override void OnResume()
{
base.OnResume();
// Register the broadcast receiver dynamically
RegisterReceiver(receiver, new IntentFilter(Resources.GetString(Resource.String.activity_intent_filter_action)));
}
protected override void OnPause()
{
base.OnPause();
UnregisterReceiver(receiver);
}
public void DisplayResult(Intent intent)
{
// Output the scanned barcode to ViewModel
barcodeModel.decodedData = intent.GetStringExtra(Resources.GetString(Resource.String.datawedge_intent_key_data));
}
}
// Broadcast receiver to receive scanned data
[BroadcastReceiver(Enabled = true)]
public class myBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
String action = intent.Action;
if (action.Equals(MainActivity.Instance.Resources.GetString(Resource.String.activity_intent_filter_action)))
{
// A barcode has been scanned
MainActivity.Instance.RunOnUiThread(() => MainActivity.Instance.DisplayResult(intent));
}
}
}
}
视图模型:
public class BarcodeModel : INotifyPropertyChanged
{
private string data;
public event PropertyChangedEventHandler PropertyChanged;
public BarcodeModel()
{
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string decodedData
{
get { return data; }
set { data = value; OnPropertyChanged(); }
}
内容页:
<Label Text="{Binding decodedData}"
HorizontalOptions="StartAndExpand"
VerticalOptions="Center"
TextColor="Accent"/>
<Entry Keyboard="Text"
Placeholder="No Object selected"
VerticalOptions="Center"
HorizontalOptions="StartAndExpand"
x:Name="eintrag"
Text="{Binding decodedData}"/>
.xaml.cs 中的 BindingContext:BindingContext = new BarcodeModel();
您在 Android 项目中更改的模型与您的 bindingContext 不同,因此它不起作用。
解决方案:
使用 messagingCenter 将模型从您的 Android 项目发送到您的共享项目并在那里更新模型:
在Android项目中,每次扫码发送消息:
public void DisplayResult(Intent intent)
{
// Output the scanned barcode to ViewModel
barcodeModel.decodedData = intent.GetStringExtra(Resources.GetString(Resource.String.datawedge_intent_key_data));
barcodeModel.decodedData = "test";
MessagingCenter.Send<object, BarcodeModel>(new object(), "barCodeScanned", barcodeModel);
}
在共享项目中,订阅该消息并更新模型:
public partial class MainPage : ContentPage
{
BarcodeModel barCodeModel;
public MainPage()
{
InitializeComponent();
barCodeModel = new BarcodeModel();
barCodeModel.decodedData = "defaultValue";
this.BindingContext = barCodeModel;
MessagingCenter.Subscribe<object, BarcodeModel>(new object(), "barCodeScanned", (sender, arg) =>
{
BarcodeModel tempbarCodeModel = arg as BarcodeModel;
barCodeModel.decodedData = tempbarCodeModel.decodedData;
});
}
}
我上传了我的测试项目here,有任何问题都可以问我。