Home > Software engineering >  How do I access the values of an entry field that is in a collection view in .Net Maui
How do I access the values of an entry field that is in a collection view in .Net Maui

Time:11-17

I need to dynamically access the values of different entry fields that are built using a collection view in Maui.

I know using the OnEntryCompleted function you are able to get the text from an entry field but I am not sure the best way to store it if you have text from multiple entry fields coming from a collection view. I was thinking of using a dictionary or array to store the values but wasnt sure if there was a better way to do it.

CodePudding user response:

  1. Get CommunityToolkit.MVVM nuget package, and you read few words about it.

  2. Set you ItemSource:

    <CollectionView ItemsSource="{Binding MyObservableCollection}...>

  3. Set your DataType, of your Item template.

    <CollectionView.ItemTemplate> <DataTemplate x:DataType="model:MyModel"...>

  4. Bind your value to the Entry in the DataTemplate.

    <Label Text="{Binding MyString}"...>

All this in related to your View XAML. Next:

  1. In your ViewModel, you add:

    ObservableCollection< MyModel > MyObservableCollection

  2. To your Models you add MyModel class, with MyString property.

There is much to be desired from CollectionView's performance. So, instead of killing the already low performance, by making changes to the interface every time you add/edit item in your collection, I strongly recommend overriding ObservableCollection class, (lets call it RangeObservableCollection) where you:

  1. Implement method, to add list of objects to the collection, without raising event each time.
  2. Add bool property to suppress notifications, and allow them when you finish editing the collection. (Bonus points if you can detect if such notification was suppressed, and don't call refresh otherwise.)

And last, if you project is .NET6, update it to .NET7. (Again, for performance enhancement)

(If you test on android device, the CollectionView will be super lagy, change to release and the problem will be gone.)

Follow this step by step, and you will have working code, with nice architecture and decent performance.

CodePudding user response:

Each row of a collection view is associated with some item, an element of the CollectionView.ItemsSource.
Consider ItemsSource = ObservableCollection<MyModel> MyItems.

Add to MyModel a property (e.g. public string MyEntryValue { get; set; }),
then bind entry field's Text property to that property:
<Entry Text="{Binding MyEntryValue}" ... />

Thus, MyItems can be enumerated, to find all the texts.

Read about MVVM and DataBinding for further explanation.

CodePudding user response:

I give you my workaround here.

I prefer to use a Dictionary to store different entry value as I can clearly know each Entry's Text. I suppose that you used a MVVM structure, and so i did.

First in the View "MainPage.xaml", just make some binding here:

<CollectionView    x:Name="collcn"
                   ItemsSource="{Binding ItemCollection}"
                   ...>
               
        <CollectionView.ItemTemplate>
            <DataTemplate >
                <StackLayout>
                    <Entry Text="{Binding Text}" BackgroundColor="Yellow" TextColor="Black"/>
                </StackLayout>           
            </DataTemplate>
         </CollectionView.ItemTemplate>
</CollectionView>

Then our model, call it MyItem.cs:

public class MyItem 
{
    public int Identifier { get; set; } // that's the key which identify each entry
    public Dictionary<int, string> EntryDictionary { get; set; }
    private string _text;
    public string Text
    {
        get
        {
            return _text;
        }
        set
        {
            _text = value;
            EntryDictionary[Identifier] = Text; // the key is the Identifier and the value is the entry text. It modified the EntryDictionary in ViewModel
        }
    }

    public MyItem()
    {
        EntryDictionary = new Dictionary<int, string>(); // just do some initialization
    }

Finally, comes our ViewModel:

public class MainPageViewModel
{
    public ObservableCollection<MyItem> ItemCollection { get; set; }
    public Dictionary<int,string> EntryDictionary { get; set; } // store the text of entry

    public MainPageViewModel()
    {
        ItemCollection = new ObservableCollection<MyItem>();
        EntryDictionary = new Dictionary<int, string>();
        CreateItemCollection();
    }

    public void CreateItemCollection()
    {
        ItemCollection.Add(
            new MyItem
            {
                Identifier = 1, // when we create our MyItem, set the Identifier that identify the entry
                Text = "text1",
                EntryDictionary = EntryDictionary 
            }
            );
     ...
     }

I do know that there might be many solutions but it worked well for me.

Hope my answer could help you.

  • Related