Xamarin窗体可观察到的集合绑定到列表视图不会显示

时间:2019-01-30 12:30:17

标签: c# xamarin data-binding xamarin.forms binding

编码入门。我的视图遇到问题,无法绑定我的UserModel类型的Observable集合。数据是通过Debug.WriteLine显示的,它不会绑定到View。这是我的代码。

视图-由ItemsSource设置的绑定。

<?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:ic="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin"
         x:Class="Monger.View.HomePage">
<ContentPage.Content>
    <StackLayout  Orientation="Vertical">
        <StackLayout Orientation="Horizontal" Padding="25,0,15,10" Margin="0,10,0,0">
                <StackLayout Orientation="Horizontal" Padding="10,0,5,0">
                    <ic:CircleImage HeightRequest="60" WidthRequest="60" Aspect="AspectFill" Source="http://placekitten.com/400/300" HorizontalOptions="Start"/>
                    <Label Margin="9,0,0,0" VerticalOptions="CenterAndExpand" HorizontalOptions="EndAndExpand" FontSize="30" TextColor="#A3D1F5" Text="{Binding DeviceEui}"/>
                </StackLayout>
            </StackLayout>
            <BoxView HeightRequest="1" BackgroundColor="Black" HorizontalOptions="FillAndExpand" />
        <StackLayout Padding="20,0,20,0" Margin="0,10,0,0">
            <ListView x:Name="DeviceListView" SelectedItem="{Binding DeviceSelected}" ItemSelected="DeviceList_ItemSelected" ItemsSource="{Binding DevicesDisplay}"  Header="Devices" SeparatorColor="#A3D1F5">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextCell Text="{Binding DeviceEui}"/>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
        <StackLayout Margin="0,0,0,30" Padding="20,0,20,0">
            <Button Text="Add Device" BorderRadius = "20" BackgroundColor="#A3D1F5" Command="{Binding AddDeviceCommand}"/>
        </StackLayout>
    </StackLayout>
</ContentPage.Content>
</ContentPage>

查看背后的代码-将慢慢摆脱这里的大部分代码,以使它们成为MVVM。目前,它只是检查权限,如果可以,则触发LoadDevicesCommand,将绑定上下文设置为HomePageViewModel并初始化新的HomePageViewModel。

namespace Monger.View
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class HomePage : ContentPage
{
    public HomePage ()
    {

        InitializeComponent ();
        ViewModel = new HomePageViewModel(new PageService());
    }


    protected async override void OnAppearing()
    {

        try
        {
            var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Location);
            if (status != PermissionStatus.Granted)
            {
                if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Location))
                {
                    await DisplayAlert("Need location", "We need your location to display where you are on the map.", "OK");
                }

                var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Location);
                //Best practice to always check that the key exists
                if (results.ContainsKey(Permission.Location))
                    status = results[Permission.Location];
            }

            if (status == PermissionStatus.Granted)
            {
                ViewModel.LoadDevicesCommand.Execute(this);
                base.OnAppearing();
            }
            else if (status != PermissionStatus.Unknown)
            {
                await DisplayAlert("Location Denied", "Can not continue, try again.", "OK");
            }
        }
        catch (Exception)
        { };

    }


    private HomePageViewModel ViewModel
    {
        get { return BindingContext as HomePageViewModel; }
        set { BindingContext = value; }
    }

    private void DeviceList_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        ViewModel.DeviceSelectedCommand.Execute(e.SelectedItem);
    }
}

}

视图模型-首次使用Sqlite创建表,然后在启动时获取表(如果尚不存在)。为将来设置上下文操作,但无法使绑定生效。添加设备将添加一个UserModel对象,将其插入sql数据库中,然后将其添加到UserModel类型的Observable集合中。应该已触发“属性更改”来更新绑定。

namespace Monger.ViewModel
{
class HomePageViewModel : BaseViewModel
{
    private HttpClient _client = new HttpClient();
    private ObservableCollection<UserModel> _devices;
    private readonly IPageService _pageService;
    private UserModel _deviceSelected;
    public UserModel DeviceSelected { get { return _deviceSelected; } set { SetValue(ref _deviceSelected, value); } }

    private List<UserModel> _userDevices;
    private SQLiteAsyncConnection _connection;

    public ObservableCollection<UserModel> DevicesDisplay
    {
        get { return _devices; }
        set { SetValue(ref _devices, value); }
    }

    public String _deviceEui;

    public ICommand DeviceSelectedCommand { get; private set; } 
    public ICommand AddDeviceCommand { get; private set; }
    public ICommand LoadDevicesCommand { get; private set; }

    public HomePageViewModel(IPageService pageService)
    {
       _connection = DependencyService.Get<ISQLiteDb>().GetConnection();
        _pageService = pageService;
        LoadDevicesCommand = new Command(GetSqlConnection);
        AddDeviceCommand = new Command(AddDevice);
        DeviceSelectedCommand = new Command<UserModel>(async vm => await OnDeviceSelected(vm));
    }

    private async void GetSqlConnection() {
        await _connection.CreateTableAsync<UserModel>();
        _userDevices = await _connection.Table<UserModel>().ToListAsync();
        DevicesDisplay = new ObservableCollection<UserModel>(_userDevices);
    }


    private async Task OnDeviceSelected(UserModel Selected)
    {
        if (Selected == null)
            return;
        DeviceSelected = null;

        _deviceEui = Selected.DeviceEui;

        await _pageService.PushModalAsync(new MapPage(_deviceEui));
    }

    public async void AddDevice() {
        var userdevice = new UserModel { DeviceEui = "0000000000000777", DeviceName = "Ryans Laptop", DeviceCategory = "phone.png" };
        await _connection.InsertAsync(userdevice);
        DevicesDisplay.Add(userdevice);
        Debug.WriteLine(_devices[0].DeviceCategory);
    }
}

}

BaseViewModel-来自Mosh教程的代码

namespace Monger.ViewModel
{
public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new 
PropertyChangedEventArgs(propertyName));
    }

    protected void SetValue<T>(ref T backingField, T Value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingField, Value))
            return;
        backingField = Value;
        OnPropertyChanged(propertyName);
    }
}
}

2 个答案:

答案 0 :(得分:1)

您没有绑定Listview的ItemsSource

<ListView x:Name="DeviceListView" ItemsSource="{Binding DevicesDisplay}"   SelectedItem="{Binding DeviceSelected}" ItemSelected="DeviceList_ItemSelected" Header="Devices" SeparatorColor="#A3D1F5">

答案 1 :(得分:0)

已解决:在列表视图和显示的数据上将hasUnevenRows设置为true。