I have set up a new MAUI application and started to structure the application for the MVVM Pattern with a folder for Views, Viewmodels and Models. The root folder only containing the App.xaml and AppShell.xaml and the MauiProgram.cs.
I have setup the navigation in the shell and am able to navigate to the different views. One of my views is basically a list with a hovering button in the bottom right corner. When i click this button I show a Community Toolkit popup containing a textinput and a button. When I press this button I want to add an Item to a list.
So I set a View "DailyPage" and a Viewmodel "DailyViewModel". The Viewmodel code looks like this:
public class DailyViewModel : ViewModelBase
{
ObservableRangeCollection<ExampleModel> _DailyList { get; set;}
public ObservableRangeCollection<ExampleModel> DailyList
{
get => _DailyList;
set
{
_DailyList = value;
}
}
public AsyncCommand RefreshCommand { get; }
public DailyViewModel()
{
Title = "Daily Page";
AddObjectCommand= new MvvmHelpers.Commands.Command(AddObject);
RefreshCommand = new AsyncCommand(Refresh);
_DailyList = new ObservableRangeCollection<ExampleModel>
{
new ExampleModel{ Name = "Test1" },
new ExampleModel{ Name = "Test2" },
new ExampleModel{ Name = "Test3" },
new ExampleModel{ Name = "Test4" }
};
}
string addName = "-";
public string AddName
{
get => addName;
set => SetProperty(ref addName, value);
}
public ICommand AddObjectCommand { get; }
void AddObject()
{
ExampleModel ex = new ExampleModel() { Name = AddName };
_DailyList.Add(ex);
}
The DailyPage view looks like this:
<AbsoluteLayout>
<ListView BackgroundColor="Transparent"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="PositionProportional,HeightProportional,WidthProportional"
Margin="10"
ItemsSource="{Binding DailyList,Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:ExampleModel">
<ViewCell>
<Grid Padding="5"
HorizontalOptions="Center">
<Label Text="{Binding Name}"
FontSize="Large"
VerticalOptions="Center"
HorizontalOptions="Center"
Grid.Column="1"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Text="+"
FontSize="Large"
FontAttributes="Bold"
AbsoluteLayout.LayoutBounds="1,1,100,100"
AbsoluteLayout.LayoutFlags="PositionProportional"
Margin="10"
Clicked="onAddEntryClicked"/>
</AbsoluteLayout>
The Entry popup where the data shall be entered looks like this:
<toolkit:Popup.BindingContext>
<viewmodels:DailyViewModel/>
</toolkit:Popup.BindingContext>
<VerticalStackLayout>
<Label Text="Name"
FontSize="Large"/>
<Entry Text="{Binding AddName}"/>
<Button Command="{Binding AddObjectCommand}"
Text="Add"/>
</VerticalStackLayout>
I also have referenced to the DailyViewModel in both the DailyPage and the AddEntryPopup like this:
x:DataType="viewmodels:DailyViewModel"
so the Compiled DataBinding and the Intellisense works as intended.
Up until the adding of data via the command everything works as expected. I navigate to the view, I see a list with the example data I added to the list in the viewmodel. When I press the "+" Button the popup shows and lets me enter the data. When the "Add" button is pressed even the "AddObjectCommand" is executed and when I debug it and look in the watchlist the object is successfully added.
I was expecting, that when I add an Object to the ObservableRangeCollection, this object will later be found in my List as I set up a databinding to that observableRangeCollection. But I found that everytime I execute the AddObjectCommand, the Collection only contains of the items that I set up as demo data (Test1, Test2, Test3, Test4) but not the ones I already added.
Why is this data lost even though the actual view is not changed? How would you store data so it isnt lost when you change views?
Initially I thought the problem will occur when I start switching views, as data is not stored globally in an MVVM pattern, but it seems that data is also not retained when working with a viewmodel. This is my first time really trying to use the MVVM patterns. I have read a lot about it and I think I got the structure and the goal, but I seem to fail on the execution. Edit: DailyPage Codebehind
public partial class DailyPage : ContentPage
{
public DailyPage()
{
InitializeComponent();
}
async void onAddEntryClicked(object sender, EventArgs e)
{
var entryPopup = new AddEntryPopup();
await this.ShowPopupAsync(entryPopup);
}
}
BindingContextin your particular scenario. Also, please show how you instantiate the popup. Currently, you're creating a new instance of the ViewModel everytime, because of this line:<viewmodels:DailyViewModel/>. You should reuse the ViewModel instead of instantiating it with every new popup.