简体   繁体   中英

data Binding inside Viewmodel outside Collectionview Xamarin is not working, ui is not updating

right now i trying to implement a collectionview and a selection of different user. To get the number of selected user, i define a variable outside of the obersavle collection called _nrofselectedUser. Its the same number than the count() of the SelectedUser ObservableList that i defined. the ObservableCollection is working fine, i get all the things and its updating the ui, when deleting an object inside of it. But i unable to get the Databinding for the nrofselectedUser right.

This is the Mainpage which initialise the VielModel:

public partial class UserCollectionPage : ContentPage
{

    private UserCollectionViewModel _uvm;
    private UserDBHelper userDBHelper = new UserDBHelper();
    private int _nrOfSelectedUser { get; set; }
    public UserCollectionPage()
    {
        BindingContext = _uvm = new UserCollectionViewModel();
        InitializeComponent();

    }

This is the ModelView, called UserCollectionViewModel:

namespace App1.ViewModels { public class UserCollectionViewModel: BaseViewModel { private ObservableCollection _user;

    public ObservableCollection<object> _selectedUser { get; set; }

    private SelectionMode _selectionMode = SelectionMode.None;

    private int _nrOfSelectedUser { get; set; }

    public User SelectedItem { get; set; }

    public SelectionMode SelectionMode { get => _selectionMode; set => SetProperty(ref _selectionMode, value); }

    public ObservableCollection<User> User { get => _user; set => _user = value; }

    public ObservableCollection<object> SelectedUser { get => _selectedUser; set => _selectedUser = value; }

    public UserDBHelper userDBHelper = new UserDBHelper();

    public UserCollectionViewModel()
    {
        InitData();
        
        ShareCommand = new Command(OnShare);
        LongPressCommand = new Command<User>(OnLongPress);
        ClearCommand = new Command(OnClear);
        PressedCommand = new Command<User>(OnPressed);
        RefreshCommand = new Command(ExecuteRefreshCommand);
    }

    private void InitData()
    {
        _selectedUser = new ObservableCollection<object>();
        _user = userDBHelper.GetAllUserToCollection();
        _nrOfSelectedUser = SelectedUser.Count();
    }

    public int NrofSelectedUser
    {
        get => _nrOfSelectedUser;
        set
        {
            _nrOfSelectedUser = value;
            OnPropertyChanged(nameof(NrofSelectedUser));
        }
    }

    private void OnLongPress(User p)
    {
        try
        {
            // Use default vibration length
            Vibration.Vibrate();
            Console.WriteLine("LongPressed");
            if (_selectionMode == SelectionMode.None)
            {
                SelectionMode = SelectionMode.Multiple;
                SelectedUser.Add(p);
                _nrOfSelectedUser++;
                Console.Write("Add User");
            }
        }
        catch (FeatureNotSupportedException ex)
        {
            Console.WriteLine("Feature not supported on device" + ex);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

    private async void OnPressed(User obj)
     {
        Console.WriteLine("User In Collection: " + SelectedUser.Count());
        if (_selectionMode != SelectionMode.None)
        {
            _nrOfSelectedUser++;
            Console.WriteLine("Test OnPress");
            if (_selectedUser.Count() == 0)
            {
                SelectionMode = SelectionMode.None;
            }
            else
            {
                Console.WriteLine("Test OnPress");
            }
            
        }
        else
        {
            await  App.Current.MainPage.DisplayToastAsync("Navigiere zu User Details");
        }
    }

And this is the XAML for the MainPage

        <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
         x:Class="App1.View.UserCollectionPage"
         xmlns:pg="clr-namespace:App1.ViewModels"
         x:Name="UserCollectionView"
         xmlns:converters="clr-namespace:App1.Methods;assembly=App1">
<ContentPage.Resources>
    <ResourceDictionary>
        <converters:IntToString x:Key="IntToString" />
    </ResourceDictionary>
</ContentPage.Resources>
<NavigationPage.TitleView>
    <Grid >

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="0.5*"/>
            <ColumnDefinition Width="0.5*"/>

        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Label Grid.Column="0"
           MaxLines="1"
           Text="Patienten"
           FontSize="Medium"
           HorizontalOptions="StartAndExpand"
           VerticalOptions="Center"/>
        <StackLayout Grid.Column="1" 
                     HorizontalOptions="EndAndExpand"
                     Orientation="Horizontal">
        <Label Text="Selected:"
           VerticalOptions="Center"
           FontSize="Medium"
               HorizontalOptions="EndAndExpand"/>
            <Label Text="{Binding Path=BindingContext.NrofSelectedUser, Source={x:Reference UserCollectionView},Converter={StaticResource IntToString}}" VerticalOptions="Center" FontSize="Medium" HorizontalOptions="EndAndExpand"/>
            <Image
            Grid.Column="2" Source="https://img.icons8.com/external-tulpahn-flat-tulpahn/64/fa314a/external-bin-mobile-user-interface-tulpahn-flat-tulpahn.png"
                HorizontalOptions="EndAndExpand"/>
        </StackLayout>
    </Grid>
</NavigationPage.TitleView>

<StackLayout>
    <CollectionView x:Name="UserCV" SelectionMode="{Binding SelectionMode}" SelectedItems="{Binding SelectedUser}" ItemsSource="{Binding User}"

As you can see in the NavigationPage.TitleView i want to set the nrofselectedUser, so that it changes, when the selectedUser changes. But it isnt working, and i tried different things:

1. <Label Text="{Binding NrofSelectedUser}" so just Binding without anything

2. <Label Text="{Binding NrofSelectedUser, Converter={StaticResource IntToString}" Binding and converting the Integer to a string variable

3. <Label Text="{Binding Path=BindingContext.NrofSelectedUser, Source={x:Reference UserCollectionView}}" Binding with parent referenz to the contentpage of the usercollectionView Xaml

So on every Attempt, the initialising of the nrofselectedUser is working on InitData(). So the number is at first 0, which is correct and also got displayed in the app.

But after that, when i select User in the collectionview, the UI is not updating, no matter what i tried.

In Debug, i can see, that the value is changing depending on the pressing, but i also set nrofselectUser = SelectedUser.Count()

So i dont know why databinding is not working,

I think its something to do, that ++ or nrofselectUser = SelectedUser.Count() is not calling the onpropertychanged method in the baseView. but i dont know how to trigger it...

Please help

and btw, the BaseViewModel

public abstract class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

you are incrementing the private variable

_nrOfSelectedUser++;

instead, you need to increment the public property , which is what will cause the PropertyChanged to fire

NrofSelectedUser++;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM