Reputation: 27
I am still learning Xamarin.Forms, so please bear with me.
I am developing a control, that let's you take pictures with your camera, displays them in a FlowListView and then ultimately I want to take these pictures, turn them into E-Mail attachments and send them off.
While the Gallery part of the control is working and the E-Mail part was already written by somebody else, for some reason I can't access the control's ViewModel from my E-Mail Code-Behind.
I wrote the control in MVVM, the E-Mail part is written in xaml with code-behind.
Whenever I try to access the ImagePickerViewModel to get the contents of my AttachmentList, I get returned null.
I have already tried not initializing the ImagePickerViewModel in the E-Mail code-behind, it still returns null.
What would be the correct way to do this?
ImagePickerViewModel.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public class ImagePickerViewModel : BindableObject, INotifyPropertyChanged
{
// HERE WOULD BE A TON OF DEPENDENCIES
public ImagePickerViewModel()
{
// Commands
TakePictureCmd = new Command(TakePicture);
//ObservableCollection
TakenPicturesList = new ObservableCollection<Model.ImagePicker>();
AttachmentList = new List<BaseObject>();
}
public event PropertyChangedEventHandler PropertyChanged;
public Model.ImagePicker NewPicture { get; set; }
public BaseObject attachment { get; set; }
public List<BaseObject> AttachmentList { get; set; }
public ObservableCollection<Model.ImagePicker> TakenPicturesList { get; set; }
public string selectedImage { get; set; }
public string Path
{
get { return NewPicture.ImagePath; }
set { NewPicture.ImagePath = value; OnPropertyChanged(nameof(Path)); }
}
public Command TakePictureCmd { get; set; }
private async void TakePicture()
{
var path = await _cameraService.TakePictureAsync();
TakenPicturesList.Add(new Model.ImagePicker { ImagePath = path });
GetFilesForAttachment(path);
}
private void GetFilesForAttachement(string filePath)
{
attachment = Attachment.FromFile(filePath);
if (attachment != null)
{
AttachmentList.Add(attachment);
}
}
public void RaisedOnPropertyChanged(string _PropertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(_PropertyName));
}
}
ImagePickerView.xaml
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView"
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:local="clr-namespace:SolIT.Mobile.Client"
xmlns:vm="clr-namespace:SolIT.Mobile.Client.Features.Shared.Controls.ImagePicker.ViewModel"
xmlns:buttons="clr-namespace:Syncfusion.XForms.Buttons;assembly=Syncfusion.Buttons.XForms"
x:Class="SolIT.Mobile.Client.Features.Shared.Controls.ImagePicker.View.ImagePickerView"
x:Name="View_ImagePickerView">
<ContentView.BindingContext>
<vm:ImagePickerViewModel ContextView="{x:Reference View_ImagePickerView}"/>
</ContentView.BindingContext>
<Frame>
<ContentView.Content>
<StackLayout>
<Grid
ColumnSpacing="0"
HorizontalOptions="CenterAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<buttons:SfButton
x:Name="Btn_takePicture"
Grid.Column="1"
Text="{local:Translate Common.SelectFilesPage.TakePicture}"
TextColor="Black"
ImageSource="{Binding TakePictureIcon}"
ShowIcon="true"
BackgroundColor="Transparent"
ImageAlignment="Top"
HorizontalOptions="FillAndExpand"
Margin="3"
CornerRadius="5"
Command="{Binding TakePictureCmd}"/>
</Grid>
<BoxView Grid.ColumnSpan="2" Grid.Row="1" HeightRequest="1" BackgroundColor="{StaticResource Win10Devider}"/>
<flv:FlowListView x:Name="pictureFlowListView" SeparatorVisibility="None" HasUnevenRows="true"
FlowColumnMinWidth="110" FlowItemsSource="{Binding TakenPicturesList}">
<!--FlowItemTappedCommand="{Binding PictureTappedCmd}"
FlowLastTappedItem="{Binding SelectedItem}"-->
<flv:FlowListView.FlowColumnTemplate>
<DataTemplate>
<Grid Padding="3">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout>
<ffimageloading:CachedImage HeightRequest="100" Aspect="AspectFill"
DownsampleHeight="100" DownsampleUseDipUnits="false" x:Name="imageCached"
Source="{Binding ImagePath}">
<ffimageloading:CachedImage.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.PictureTappedCmd, Source={x:Reference pictureFlowListView}}" CommandParameter="{x:Reference imageCached}"></TapGestureRecognizer>
</ffimageloading:CachedImage.GestureRecognizers>
</ffimageloading:CachedImage>
</StackLayout>
</Grid>
</DataTemplate>
</flv:FlowListView.FlowColumnTemplate>
</flv:FlowListView>
</StackLayout>
</ContentView.Content>
</Frame>
</ContentView>
EmailCreatePage.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class EmailCreatePage: ContentPage
{
// HERE WOULD BE A TON OF DEPENDENCIES
public EmailCreateViewModel ViewModel { get; }
public ImagePickerViewModel ViewModelImagePicker {get;}
public EmailCreatePage()
{
InitializeComponent();
BindingContext = ViewModel = new EmailCreateViewModel();
ViewModelImagePicker = new ImagePickerViewModel();
}
private void CreateAttachment()
{
var attachmentList = GetFileList();
foreach (var file in attachmentList)
{
var attachment = Attachment.FromFile(file.ToString());
if (attachment != null)
{
ViewModel.CubesMessage.ConnectedObjects.Add(attachment);
}
}
public List<BaseObject> GetFileList()
{
// GET LIST FROM OTHER VIEWMODEL HERE
// VIEWMODEL IS ALWAYS NULL
var attachmentList = ImagePickerViewModel.AttachmentList;
return attachmentList;
}
// HERE WOULD BE THE CODE THAT SENDS THE EMAIL OFF AFTER A BUTTON CLICK
Upvotes: 0
Views: 456
Reputation: 13949
From the following code you posted , we find that you want to access variable AttachmentList
from ImagePickerViewModel
. But here, you just create a new instance of class ImagePickerViewModel
, so the attachmentList
will always be null.
ViewModelImagePicker = new ImagePickerViewModel();
Besides, you also use code ImagePickerViewModel.AttachmentList;
to access variable AttachmentList
in ImagePickerViewModel
, that's confusing. Here, you can remove code ViewModelImagePicker = new ImagePickerViewModel();
.
public List<BaseObject> GetFileList()
{
// GET LIST FROM OTHER VIEWMODEL HERE
// VIEWMODEL IS ALWAYS NULL
var attachmentList = ImagePickerViewModel.AttachmentList;
return attachmentList;
}
In fact, if you want to get the value of variable AttachmentList
in class ImagePickerViewModel
from other page, you can define a global static
varible AttachmentList
.
Just as follows:
public stactic List<BaseObject> AttachmentList { get; set; }
Note: Make sure AttachmentList
in class ImagePickerViewModel
could been assigned values correctly.
Upvotes: 2