Xamarin中XAML与XAML.cs绑定失效,如何正确配置DataContext?
Xamarin数据绑定问题:无法识别绑定变量,如何正确设置DataContext?
我是Xamarin新手,尝试将.xaml.cs中的数据绑定到.xaml文件,但应用无法识别绑定的变量。请问应如何正确使用DataContext来建立绑定连接?
以下是我的代码:
MainPage.xaml.cs
using System; using System.Windows; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; using Plugin.BLE; using Plugin.BLE.Abstractions.Contracts; using Plugin.BLE.Abstractions.Exceptions; using Xamarin.Forms; namespace BT { public partial class MainPage : ContentPage { #region MAINPAGE CONSTRUCTOR public MainPage() { InitializeComponent(); initializeBluetooh(); } #endregion #region BT constructor #endregion #region BT VARIABLES // bluetooth IBluetoothLE _handler; IAdapter _adapter; ObservableCollection<IDevice> _devicelist; ObservableCollection<IDevice> _devicelistAux; IDevice _connectedDevice; String _deviceName; String _bt_state; IReadOnlyList<IService> _services; Task<IReadOnlyList<ICharacteristic>> _characteristics; ICharacteristic _characteristic; IService _service; String _stringBuff; private Guid guid; IDevice deviceConn; #endregion #region BT OBJECTS public ObservableCollection<IDevice> devicelist { get { return _devicelist; } set { _devicelist = value; } } public IDevice connectedDevice { get { return _connectedDevice; } set { _connectedDevice = value; } } public IBluetoothLE handler { get { return _handler; } set { _handler = value; } } public IAdapter adapter { get { return _adapter; } set { _adapter = value; } } public IReadOnlyList<IService> services { get { return _services; } set { _services = value; } } public Task<IReadOnlyList<ICharacteristic>> characteristics { get { return _characteristics; } set { _characteristics = value; } } public IService service { get { return _service; } set { _service = value; } } public ICharacteristic characteristic { get { return _characteristic; } set { _characteristic = value; } } public String bt_state { get { return _bt_state; } set { _bt_state = value; } } #endregion #region BT FUNCTIONS public async void initializeBluetooh() { handler = CrossBluetoothLE.Current; adapter = CrossBluetoothLE.Current.Adapter; adapter.ScanMode = ScanMode.LowPower; adapter.ScanTimeout = 5000; devicelist = new ObservableCollection<IDevice>(); bt_state = "BLUETOOTH INFO:\n"; Console.WriteLine(bt_state); } public async void InitScanDevices(object sender, EventArgs e) { bt_state = "BLUETOOTH INFO:\n" + "\nBluetooth state: Scanning..."; Console.WriteLine(bt_state); devicelist.Clear(); adapter.DeviceDiscovered += (s, args) => { IDevice dispositivoDescubierto = args.Device; devicelist.Add(dispositivoDescubierto); Console.WriteLine(dispositivoDescubierto.Name); }; if (!handler.Adapter.IsScanning) { await adapter.StartScanningForDevicesAsync(); bt_state = "BLUETOOTH INFO:\n" + "\nBluetooth state: Stopped Scanning"; Console.WriteLine(bt_state); } } public async void OnCollectionViewSelectionChanged(object sender, SelectedItemChangedEventArgs e) { if (adapter.IsScanning) { await adapter.StopScanningForDevicesAsync(); } var selectedDevice = (IDevice)e.SelectedItem; Console.WriteLine(selectedDevice.Name); try { Device.BeginInvokeOnMainThread(() => { adapter.ConnectToDeviceAsync(selectedDevice); deviceConn = selectedDevice; }); } catch (DeviceConnectionException) { //DisplayAlert("Error", "Could not connect to device", "Dismiss"); } } #endregion #region BT COMMANDS #endregion } }
MainPage.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="BT.MainPage"> <StackLayout> <Label Margin="0,50,0,0"/> <Frame OutlineColor="White"> <Label Text="BLUETOOTH CONNECTION" TextColor="Coral" /> </Frame> <Frame OutlineColor="DarkBlue"> <Label Text="{Binding bt_state}"/> </Frame> <Button Clicked="InitScanDevices" Text="Scan for devices"/> <ListView SelectionMode="Single" ItemSelected="OnCollectionViewSelectionChanged" ItemsSource="{Binding devicelist}" BackgroundColor="Aqua"> <ListView.ItemTemplate> <DataTemplate> <TextCell Text="{Binding Name}" TextColor="Black"/> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage>
解决步骤
1. 设置页面的DataContext
XAML绑定需要明确数据源,在页面构造函数中把DataContext设置为当前页面实例,让XAML知道要绑定的数据来自哪里:
public MainPage() { InitializeComponent(); // 设置数据源为当前页面 DataContext = this; initializeBluetooh(); }
2. 实现INotifyPropertyChanged接口更新UI
当前代码中bt_state属性变化时,UI不会自动刷新,因为缺少属性变更通知机制。需要让MainPage实现INotifyPropertyChanged接口:
首先修改类定义:
public partial class MainPage : ContentPage, INotifyPropertyChanged { // 声明属性变更事件 public event PropertyChangedEventHandler PropertyChanged; // 触发事件的辅助方法 protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
然后修改bt_state的setter,在赋值后触发通知:
public String bt_state { get { return _bt_state; } set { _bt_state = value; // 通知UI属性已更新 OnPropertyChanged(nameof(bt_state)); } }
3. 优化ObservableCollection的绑定
devicelist是ObservableCollection<IDevice>,本身支持集合元素变更通知,但如果直接重新赋值集合,也需要触发属性变更通知:
public ObservableCollection<IDevice> devicelist { get { return _devicelist; } set { _devicelist = value; OnPropertyChanged(nameof(devicelist)); } }
4. 确保UI操作在主线程
在InitScanDevices中更新bt_state时,建议显式切换到主线程(Xamarin.Forms会自动处理,但显式操作更稳妥):
Device.BeginInvokeOnMainThread(() => { bt_state = "BLUETOOTH INFO:\n" + "\nBluetooth state: Stopped Scanning"; });
内容的提问来源于stack exchange,提问作者Raul
相关产品推荐
相关产品推荐

