I have issue in data binding items from collection into grid content views.
Please find below code. This is just for representation and it is part of full logic.
View Model Class
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<ChildViewModel> myProperty;
public ObservableCollection<ChildViewModel> MyProperty
{
get
{
return myProperty;
}
set
{
if (myProperty != value)
{
myProperty = value;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("MyProperty"));
}
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class ChildViewModel : INotifyPropertyChanged
{
private string prop1;
private string prop2;
public string Prop1
{
get
{
return prop1;
}
set
{
if (prop1 != value)
{
prop1 = value;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("Prop1"));
}
}
}
}
public string Prop2
{
get
{
return prop2;
}
set
{
if (prop2 != value)
{
prop2 = value;
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("Prop2"));
}
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Use of View Model Class
ChildViewModel objChildViewModel1 = new ChildViewModel { Prop1 = "Prop1", Prop2 = "Prop2" };
ChildViewModel objChildViewModel2 = new ChildViewModel { Prop1 = "Prop1", Prop2 = "Prop2" };
ViewModel obj = new ViewModel
{
MyProperty = new ObservableCollection<ChildViewModel> { objChildViewModel1,objChildViewModel2}
};
//set binding context
this.BindingContext = obj;
var grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
var Label1 = new Label { };
//how to databind obj.MyProperty[0].Prop1 to Label1 ???
var Label2 = new Label { };
//how to databind obj.MyProperty[1].Prop1 to Label2 ???
var Entry1 = new Entry { };
//how to databind obj.MyProperty[0].Prop2 to Entry1 ???
var Entry2 = new Entry { };
//how to databind obj.MyProperty[1].Prop2 to Entry2 ???
grid.Children.Add(Label1, 0, 0);
grid.Children.Add(Entry1, 0, 1);
grid.Children.Add(Label2, 1, 0);
grid.Children.Add(Entry2, 1, 1);
Here as I have shown in code, I want to databind collection from object of ViewModel class for Label1, Label2, Entry1 and Entry2. I know about basic databinding where only bind property with name to view/control in xamarin forms but here I am not able to bind it. Kindly help me here.
grid.BindingContext=obj;
Label1.SetBinding (Label.TextProperty, "MyProperty[0].Prop1");
Label2.SetBinding (Label.TextProperty, "MyProperty[1].Prop1");
Entry1.SetBinding (Entry.TextProperty, "MyProperty[0].Prop2");
Entry2.SetBinding (Entry.TextProperty, "MyProperty[1].Prop2");
Related
I have tried for the last 4 days to find an illusive image in that app, I am new to xamarin forms and a client asked me to replace an image which I did, but I have left with another image that I should implement and I can't find its source, the XML code for the specific section looks like this.
<ScrollView Grid.Row="2"
HeightRequest="50"
HorizontalOptions="CenterAndExpand"
Orientation="Horizontal"
IsVisible="{Binding PhotosVisible.Value}"
x:Name="ScrollPhotos">
<StackLayout Orientation="Horizontal"
Spacing="0"
VerticalOptions="Center"
Padding="5,0"
x:Name="StackPhotos">
</StackLayout>
</ScrollView>
and the place I'm trying to implement the photo in is:
should be an image instead of the blank grey rectengle
(should be an image instead of the blank grey rectangle)
I cant find the source to the other image, and I even deleted something that was pretty similar in the drawAble folder but it changed nothing.
any help or suggestion will be helpful, Thanks. :)
edit:
The xml.cs source code:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DashboardPage : ExtPage
{
public DashboardPage()
{
InitializeComponent();
Padding = new Thickness(0, 0, 0, MashamAppForms.Helpers.Settings.NativeSetting.BottonPadding);
NavigationPage.SetHasBackButton(this, false);
}
protected override void OnAppearing() {
MessagingCenter.Subscribe<Application>(App.Current, "DashboardFillDates", FillDates);
MessagingCenter.Subscribe<Application, CPhoto[]>(App.Current, "DashboardFillPhotos", FillPhotos);
base.OnAppearing();
}
protected override void OnDisappearing() {
MessagingCenter.Unsubscribe<Application>(App.Current, "DashboardFillDates");
base.OnDisappearing();
}
void FillPhotos(Application arg1, CPhoto[] arg2) {
var bc = (DashboardViewModel)BindingContext;
StackPhotos.Children.Clear();
if (arg2 == null)
return;
foreach (var photo in arg2) {
var image = new CachedImage {
Aspect = Aspect.AspectFill,
Source = photo.Path,
BackgroundColor = Color.FromHex("#504F77AB"),
DownsampleHeight = 100,
HeightRequest = 40,
WidthRequest = 60,
Margin = new Thickness(5, 0)
};
Commands.SetTap(image, bc.ViewImageCommand);
Commands.SetTapParameter(image, photo);
StackPhotos.Children.Add(image);
}
Device.BeginInvokeOnMainThread(() => {
try {
ScrollPhotos.ScrollToAsync(StackPhotos.Children.LastOrDefault(), ScrollToPosition.End, false);
}
catch {
}
});
}
void FillDates(Application application) {
var bc = (DashboardViewModel)BindingContext;
var dates = bc.Dates;
StackDates.Children.Clear();
if (dates == null)
return;
for (var i = 0; i < dates.Length; i++) {
var t = dates[i];
var grid = new Grid {
RowDefinitions =
{
new RowDefinition {Height = GridLength.Star},
new RowDefinition {Height = GridLength.Star},
new RowDefinition {Height = GridLength.Star}
},
Padding = new Thickness(5, 0),
RowSpacing = 0,
BindingContext = t
};
grid.SetBinding(Grid.BackgroundColorProperty, "BackgroundColor.Value");
var l1 = new Label {
Text = t.HebrewDay,
TextColor = t.TextColor,
HorizontalOptions = LayoutOptions.Center,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label))
};
l1.SetBinding(Label.TextColorProperty, "TextColor.Value");
grid.Children.Add(l1, 0, 0);
var l2 = new Label {
Text = t.HebrewDate,
TextColor = t.TextColor,
HorizontalOptions = LayoutOptions.Center,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label))
};
l2.SetBinding(Label.TextColorProperty, "TextColor.Value");
grid.Children.Add(l2, 0, 1);
var l3 = new Label {
Text = t.Date.ToString("dd/MM/yyyy"),
TextColor = t.TextColor,
HorizontalOptions = LayoutOptions.Center,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label))
};
l3.SetBinding(Label.TextColorProperty, "TextColor.Value");
grid.Children.Add(l3, 0, 2);
var gest = new TapGestureRecognizer {
Command = bc.ChangeDateCommand,
CommandParameter = t
};
grid.GestureRecognizers.Add(gest);
StackDates.Children.Add(grid);
if (i != dates.Length - 1)
StackDates.Children.Add(new BoxView {
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Fill,
WidthRequest = 1,
Color = (Color)Application.Current.Resources["SelectionColor"]
});
}
Device.BeginInvokeOnMainThread(() =>
{
try {
ScrollDates.ScrollToAsync(StackDates.Children.LastOrDefault(), ScrollToPosition.End, false);
}
catch {
}
});
}
}
and the viewModel.cs is:
public class DashboardViewModel : FormsBaseViewModel
{
static bool _nowAsking;
static bool _scanning;
public ICommand ChangeDateCommand { get; }
public ICommand LogoutCommand { get; }
public ICommand ListHeaderCommand { get; }
public ICommand EventCommand { get; }
public ICommand QrCommand { get; }
public ICommand ViewImageCommand { get; }
public ICommand PhotoCommand { get; }
public ICommand FeedbackCommand { get; }
public ICommand LocationCommand { get; }
public ICommand ContactsCommand { get; }
public ICommand MessagesCommand { get; }
public ICommand FileCommand { get; }
public ObservableProperty<int> CarouselPosition { get; }
public ObservableProperty<BasePageState> EventsState { get; } = new ObservableProperty<BasePageState>();
public ObservableProperty<bool> IsBusy { get; } = new ObservableProperty<bool>();
public ObservableProperty<bool> PhotosVisible { get; } = new ObservableProperty<bool>();
public SmartCollection<EventDetails> EventList { get; set; }
public Conferance Conferance { get; set; }
public bool SubtitleVisible => !string.IsNullOrEmpty(Conferance?.SubTitle);
public string Phone { get; set; }
public string Name { get; set; }
public string RealId { get; set; }
public EventDetails[] Events { get; set; }
public QrDetails[] QrDetails { get; set; }
public CPhoto[] CPhotos { get; set; }
public string FileLink { get; set; }
public string Greeting { get; set; }
public string ApiKey { get; set; }
public CParticipant[] Participants { get; set; }
public ThreeDatesItem[] Dates { get; set; }
private ThreeDatesItem _selected;
public ThreeDatesItem SelectedDate
{
get => _selected;
set
{
_selected = value;
EventList.Clear();
Task.Run(async () =>
{
await Task.Delay(100);
EventList.AddRange(GetEvents(value.Date));
});
}
}
public DashboardViewModel()
{
CarouselPosition = new ObservableProperty<int>();
EventList = new SmartCollection<EventDetails>();
ChangeDateCommand = new Command<ThreeDatesItem>(item =>
{
foreach (var tdi in Dates)
{
tdi.IsSelected = false;
}
item.IsSelected = true;
SelectedDate = item;
});
LogoutCommand = new Command(async () =>
{
Settings.Authed = false;
Settings.SavedPhone = "";
Settings.SavedId = "";
OneSignal.Current.DeleteTag("confId");
await NavigationService.Navigate<LoginViewModel>();
NavigationService.ClearNavigationStack();
});
ListHeaderCommand = new Command<EventDetails>(details =>
{
var mainColor = (Color)Application.Current.Resources["SelectionColor"];
if (details.IsOpened)
{
var del = EventList.Where(e => e.WhatMashov == details.IsMashov).ToArray();
for (var i = 0; i < del.Length; i++)
{
EventList.Remove(del[i]);
}
details.SeparatorColor.Value = mainColor;
}
else
{
var add = Events?.Where(e => e.Day == details.Day && e.WhatMashov == details.IsMashov).ToArray();
details.SeparatorColor.Value = add.Length == 0? mainColor : Color.LightGray;
var after = details;
for (var i = 0; i < add.Length; i++)
{
add[i].SeparatorColor.Value = i == add.Length - 1 ? mainColor : Color.LightGray;
add[i].GridPadding = new Thickness(10, 10, 20, 10);
EventList.Insert(EventList.IndexOf(after) + 1, add[i]);
after = add[i];
}
}
EventList.Last().SeparatorColor.Value = Color.Transparent;
details.IsOpened = !details.IsOpened;
});
EventCommand = new Command<EventDetails>(async details =>
{
await NavigationService.Navigate<EventInfoViewModel>(model =>
{
model.Participants.AddRange(Participants?.Where(e => e.EventId == details.EventId));
model.Date.Value = SelectedDate;
model.EventDetails.Value = details;
model.Phone = Phone;
model.IsVisibleDescription.Value = !string.IsNullOrEmpty(details.Description);
model.IsVisibleLecturers.Value = model.Participants.Count > 0;
model.Conferance = Conferance;
model.AllEvents = Events;
model.Name = Name;
model.SelectedEventDetails = details;
model.QrDetails = QrDetails;
});
});
QrCommand = new Command<EventDetails>(details =>
{
if (details.QrState == QrState.Normal)
NavigationService.Navigate<QrPickerViewModel>(NavigationType.Popup, m => {
m.EventDetails = Events;
m.EventId = details.EventId;
m.QrDetails = QrDetails;
m.Phone = Phone;
m.Name = Name;
m.ConfId = Conferance.Id;
});
});
ViewImageCommand = new Command<CPhoto>(p =>
{
var s = p?.Path?.Trim();
var photos = CPhotos.Select(e => new MyPhoto {
URL = e?.Path?.Trim(),
Title = string.Empty,
Link = e?.SponsorLink?.Trim()
}).ToList();
if (Device.RuntimePlatform == Device.iOS)
photos.Reverse();
var pos = photos?.FindIndex(e => e.URL == s) ?? 0;
var config = new PhotoConfig {
Photos = photos,
StartIndex = pos,
ActionButtonPressed = async (index) => {
var action = await AlertCenter.ActionSheet(Device.RuntimePlatform == Device.Android ? Localization.SelectAction : null, Localization.Cancel, null, Localization.SponsorLink);
if (action == Localization.SponsorLink) {
if (string.IsNullOrEmpty(photos[index]?.Link)) {
AlertCenter.Error(Localization.NoLink);
}
else {
Device.OpenUri(new Uri(photos[index].Link, UriKind.Absolute));
}
}
}
};
config.Show();
});
PhotoCommand = new Command(async () =>
{
await LoadingPopupService.Show();
var photos = await SimpleServerRequest.Request<CPhoto[]>(new Uri("http://app.masham.org.il/insertToConfearnce2.php?Action=getAllEvents&TableName=I_" + Conferance.Id));
await LoadingPopupService.Close();
if (photos.Item1)
await NavigationService.Navigate<PhotoGalleryViewModel>(m =>
{
m.Photos.Value = photos.Item2.Where(e => e.Type == "גלריה").ToArray();
m.ConfId = Conferance.Id;
m.ApiKey = ApiKey;
});
else
AlertCenter.Error(Localization.ErrorLoading);
});
FeedbackCommand = new Command(async () =>
{
if (string.IsNullOrEmpty(Conferance?.SurvayLink))
{
AlertCenter.Error(Localization.NoLink);
return;
}
await LoadingPopupService.Show();
var res = await SimpleServerRequest.Request(new Uri($#"http://app.masham.org.il/insertToConfearnce2.php?Action=getServerDateAndtime&CID={Conferance.Id}"));
await LoadingPopupService.Close();
try
{
if (res.Success)
{
if (res.Result.ToLower() == "true")
Device.OpenUri(new Uri(Conferance?.SurvayLink, UriKind.Absolute));
else
AlertCenter.Error(Localization.NoMashovTime);
}
else
AlertCenter.Error(Localization.ErrorLoading);
}
catch
{
AlertCenter.Error(Localization.IncorrectLink);
}
});
LocationCommand = new Command(() =>
{
Device.OpenUri(new Uri("https://waze.com/ul?q=" + Conferance?.NameOfLocation));
});
ContactsCommand = new Command(async () =>
{
await NavigationService.Navigate<ContactsViewModel>(m =>
{
m.Phone.Value = Conferance?.Phone;
m.Location.Value = Conferance?.NameOfLocation;
m.Email.Value = Conferance?.Email;
});
});
MessagesCommand = new Command(async () =>
{
await LoadingPopupService.Show();
var messages = await SimpleServerRequest.Request<CMessage[]>(new Uri(
"http://app.masham.org.il/insertToConfearnce2.php?Action=getAllEvents&TableName=" +
"Messages_" + Conferance.Id));
await LoadingPopupService.Close();
if (messages.Item1)
{
DependencyService.Get<ILocalSettings>().PushCounter = 0;
await NavigationService.Navigate<MessagesViewModel>(m =>
{
m.Messages.AddRange(messages.Item2 ?? new CMessage[0]);
m.ConfId = Conferance.Id.ToString();
});
}
else
AlertCenter.Error(Localization.ErrorLoading);
});
FileCommand = new Command(() => {
if (string.IsNullOrEmpty(FileLink)) {
AlertCenter.Error(Localization.NoLink);
return;
}
Device.OpenUri(new Uri(FileLink, UriKind.Absolute));
});
}
public async void Resumed() {
{
if (_nowAsking)
return;
_nowAsking = true;
if (NavigationService.CurrentModalPage == null && NavigationService.CurrentPage.GetType() == typeof(DashboardPage) && !LoadingPopupService.IsLoading) {
IsBusy.Value = true;
await LoadingPopupService.Show();
var users = await SimpleServerRequest.Request<UserAndConferance[]>(new Uri($"http://app.masham.org.il/apimasham.php?Action=getUser&idUsername={Phone}&realId={RealId}"));
if (users.Item1) {
var user = users.Item2.FirstOrDefault();
ApiKey = user?.ApiKey;
var conf = users.Item2.Select(e => e.Conferance).FirstOrDefault(e => e != null && e.Id == Conferance.Id);
if (conf == null) {
_nowAsking = false;
IsBusy.Value = false;
Settings.Authed = false;
Settings.SavedPhone = "";
Settings.SavedId = "";
await LoadingPopupService.Close();
await AlertCenter.ErrorAsync(Localization.ConfNotFound);
await NavigationService.Navigate<LoginViewModel>();
NavigationService.ClearNavigationStack();
return;
}
var eventContainer = await SimpleServerRequest.Request<EventContainer>(new Uri($"http://app.masham.org.il/apimasham.php?Action=getEvents&confId={Conferance.Id}&phone={Phone}"));
if (eventContainer.Item1 && eventContainer.Item2 != null) {
var dates = eventContainer.Item2.EventDetails
?.Select(e => new {
e.Day,
e.HebrewDay
})
.Distinct()
.Select(e => new ThreeDatesItem {
Date = e.Day,
HebrewDate = e.HebrewDay
})
.OrderByDescending(e => e.Date)
.ToArray();
Events = eventContainer.Item2.EventDetails ?? new EventDetails[0];
QrDetails = eventContainer.Item2.QrDetails ?? new QrDetails[0];
QrStateHelper.SetQrStatesForAll(Events, QrDetails, eventContainer.Item2.QrAnswers);
if (conf.Type == "קורס" && dates != null) {
var p = 1;
for (var i = dates.Length - 1; i >= 0; i--) {
dates[i].HebrewDate = "מפגש " + p++;
}
}
var isEqualDates = Dates != null && Dates.Length == dates?.Length && conf.Type == Conferance.Type;
if (isEqualDates)
for (var i = 0; i < dates.Length; i++) {
isEqualDates = dates[i].Date == Dates[i].Date;
if (!isEqualDates)
break;
}
if (!isEqualDates)
Dates = dates;
var photos = eventContainer.Item2.Photos?.Where(e => e.Type == "קרוסלה").ToArray();
var isEqualPhotos = CPhotos != null && CPhotos.Length == photos?.Length;
if (isEqualPhotos)
for (var i = 0; i < photos.Length; i++) {
isEqualPhotos = photos[i].Path == CPhotos[i].Path;
if (!isEqualPhotos)
break;
}
else
CPhotos = photos;
Conferance = conf;
FileLink = eventContainer.Item2.Photos?.FirstOrDefault(e => e.Type == "קובץ")?.Path;
OnPropertyChanged(nameof(Conferance));
PrepareDatesAndPhotos(!isEqualDates, !isEqualPhotos);
if (Events.Length > 0) {
EventsState.Value = BasePageState.Normal;
}
else {
EventList.Clear();
EventsState.Value = BasePageState.NoData;
}
_nowAsking = false;
IsBusy.Value = false;
await LoadingPopupService.Close();
return;
}
}
IsBusy.Value = false;
await LoadingPopupService.Close();
await AlertCenter.ErrorAsync(Localization.ErrorLoading);
}
_nowAsking = false;
}
}
public override async void FirstAppearing()
{
base.FirstAppearing();
NavigationService.ClearNavigationStack();
await Task.Delay(300);
Device.BeginInvokeOnMainThread(() => {
PrepareDatesAndPhotos();
});
}
void PrepareDatesAndPhotos(bool updDates = true, bool updPhotos = true) {
if (updPhotos)
MessagingCenter.Send(App.Current, "DashboardFillPhotos", CPhotos);
PhotosVisible.Value = CPhotos?.Any() ?? false;
if (Dates?.Any() ?? false) {
if (updDates) {
var today = Dates.FirstOrDefault(e => e.Date == DateTime.Today);
if (today != null) {
today.IsSelected = true;
SelectedDate = today;
}
else {
var date = Dates[Dates.Length - 1];
date.IsSelected = true;
SelectedDate = date;
}
MessagingCenter.Send(App.Current, "DashboardFillDates");
}
else {
SelectedDate = SelectedDate;
}
}
}
private EventDetails[] GetEvents(DateTime date)
{
var items = Events?.Where(e => e.Day == date && e.WhatMashov == "").OrderBy(e => e.StartTime).ToArray();
var mainColor = (Color)Application.Current.Resources["SelectionColor"];
if (items?.Length > 0)
{
for (var i = 0; i < items.Length; i++)
{
items[i].IsOpened = false;
if (string.IsNullOrEmpty(items[i].IsMashov) && string.IsNullOrEmpty(items[i].WhatMashov))
{
items[i].SeparatorColor.Value = mainColor;
items[i].GridPadding = new Thickness(10, 10, 10, 10);
}
else
{
items[i].GridPadding = new Thickness(10, 10, 20, 10);
if (i != items.Length - 1)
{
if (!string.IsNullOrEmpty(items[i + 1].IsMashov) ||
!string.IsNullOrEmpty(items[i + 1].WhatMashov))
{
items[i].SeparatorColor.Value = Color.LightGray;
}
else
{
items[i].SeparatorColor.Value = mainColor;
}
}
}
}
items.Last().SeparatorColor.Value = Color.Transparent;
}
return items;
}
}
I am using monkey chat in my mobile application(Xamrin forms based). While sending a message on IOS, on a real device, I have to click the send button 2 times. First time when I click, it minimizes the keyboard and 2nd time, it sends the message. Please suggest.
How do I send a message on one click?
Here is my send message function
namespace Budocode.ViewModels
{
public class MainChatViewModel : BaseViewModel
{
public ObservableRangeCollection Messages { get; }
ITwilioMessenger twilioMessenger;
string outgoingText = string.Empty;
public string OutGoingText
{
get { return outgoingText; }
set { SetProperty(ref outgoingText, value); }
}
public ICommand SendCommand { get; set; }
public ICommand LocationCommand { get; set; }
public MainChatViewModel()
{
// Initialize with default values
twilioMessenger = DependencyService.Get<ITwilioMessenger>();
Messages = new ObservableRangeCollection<ChatMessage>();
SendCommand = new Command(() =>
{
var message = new ChatMessage
{
Text = OutGoingText,
IsIncoming = false,
ProfileId = "profile" + GlobalSettingsDataSource.Current.SelectedProfileImageId + ".png",
MessageDateTime = DateTime.Now,
FromUser = GlobalSettingsDataSource.Current.SelectedProfile
};
if (string.IsNullOrWhiteSpace(OutGoingText))
return;
Messages.Add(message);
twilioMessenger?.SendMessage(message.Text, message.ProfileId, GlobalSettingsDataSource.Current.SelectedProfile);
OutGoingText = string.Empty;
});
LocationCommand = new Command(async () =>
{
try
{
var local = await CrossGeolocator.Current.GetPositionAsync(TimeSpan.FromSeconds(15));
var map = $"https://maps.googleapis.com/maps/api/staticmap?center={local.Latitude.ToString(CultureInfo.InvariantCulture)},{local.Longitude.ToString(CultureInfo.InvariantCulture)}&zoom=17&size=400x400&maptype=street&markers=color:red%7Clabel:%7C{local.Latitude.ToString(CultureInfo.InvariantCulture)},{local.Longitude.ToString(CultureInfo.InvariantCulture)}&key=";
var message = new ChatMessage
{
Text = "I am here",
AttachementUrl = map,
ProfileId = "profile" + GlobalSettingsDataSource.Current.SelectedProfileImageId + ".png",
IsIncoming = false,
MessageDateTime = DateTime.Now
};
Messages.Add(message);
twilioMessenger?.SendMessage("attach:" + message.AttachementUrl, message.ProfileId, GlobalSettingsDataSource.Current.SelectedProfile);
}
catch (Exception ex)
{
}
});
if (twilioMessenger == null)
return;
twilioMessenger.MessageAdded = (message) =>
{
//if (message.ProfileId == "Icon.png")
Device.BeginInvokeOnMainThread(() =>
{
if (message.FromUser != GlobalSettingsDataSource.Current.SelectedProfile)
{
message.IsIncoming = true;
}
else
{
message.IsIncoming = false;
}
Messages.Add(message);
});
};
}
public async void InitializeMock(string channelName)
{
try
{
var id = CrossDeviceInfo.Current.Id;
var userId = PersistantData.Current.UserAccount.Properties["user_id"];
HttpResponseMessage appResponse = CommonUtility.GetApiContent(
String.Format(ClientConfiguration.TwilioServiceChatHistory, id, GlobalSettingsDataSource.Current.SelectedProfile, channelName));
if (appResponse.IsSuccessStatusCode)
{
var chatContent = await appResponse.Content.ReadAsStringAsync();
List<ChatMessage> chatMsgs = JsonConvert.DeserializeObject<List<ChatMessage>>(chatContent);
Messages.ReplaceRange(chatMsgs);
}
}
catch
{
// ignore if there are any issues with twilio
}
}
}
}
I have implemented Complex custom Foolproof validation in my application from this link but sadly its not working.My requirement is simple,I have a input file for uploading an image and there should be a validation if the user chooses to upload file other than specified below
".jpg",".png",".gif",".jpeg"
Code is
[Required(ErrorMessage = "Please upload Photo", AllowEmptyStrings = false)]
[IsValidPhoto(ErrorMessage="Please select files of type .jpg,.png,.gif,.jpeg")]
public HttpPostedFileBase PhotoUrl { get; set; }
public class IsValidPhotoAttribute : ModelAwareValidationAttribute
{
//this is needed to register this attribute with foolproof's validator adapter
static IsValidPhotoAttribute() { Register.Attribute(typeof(IsValidPhotoAttribute)); }
public override bool IsValid(object value, object container)
{
if (value != null)
{
string[] AllowedFileExtensions = new string[] { ".jpg", ".gif", ".png", ".jpeg" };
var file = value as HttpPostedFileBase;
if (!AllowedFileExtensions.Contains(file.FileName.Substring(file.FileName.LastIndexOf('.'))))
{
return false;
}
}
return true;
}
}
CSHTML is
#Html.TextBoxFor(m => m.PhotoUrl, new { #class = "form-control imgUpload",
#placeholder = "Please upload Photo", #id = "txtPhoto", #type = "file" })
#Html.ValidationMessageFor(m => m.PhotoUrl)
You will not be able to get client side validation unless you also create a script to add the rules. It is not necessary to use foolproof and the following method and scripts will give you both server and client side validation
public class FileAttachmentAttribute : ValidationAttribute, IClientValidatable
{
private List<string> _Extensions { get; set; }
private const string _DefaultErrorMessage = "Only file types with the following extensions are allowed: {0}";
public FileAttachmentAttribute(string fileExtensions)
{
_Extensions = fileExtensions.Split('|').ToList();
ErrorMessage = _DefaultErrorMessage;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
HttpPostedFileBase file = value as HttpPostedFileBase;
if (file != null)
{
var isValid = _Extensions.Any(e => file.FileName.EndsWith(e));
if (!isValid)
{
return new ValidationResult(string.Format(ErrorMessageString, string.Join(", ", _Extensions)));
}
}
return ValidationResult.Success;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ValidationType = "fileattachment",
ErrorMessage = string.Format(ErrorMessageString, string.Join(", ", _Extensions))
};
rule.ValidationParameters.Add("extensions", string.Join(",", _Extensions));
yield return rule;
}
}
Scripts
$.validator.unobtrusive.adapters.add('fileattachment', ['extensions'], function (options) {
var params = { fileattachment: options.params.extensions.split(',') };
options.rules['fileattachment'] = params;
if (options.message) {
options.messages['fileattachment'] = options.message;
}
});
$.validator.addMethod("fileattachment", function (value, element, param) {
var extension = getExtension(value);
return $.inArray(extension, param.fileextensions) !== -1;
});
function getExtension(fileName) {
var extension = (/[.]/.exec(fileName)) ? /[^.]+$/.exec(fileName) : undefined;
if (extension != undefined) {
return extension[0];
}
return extension;
};
and then use it as
[FileAttachment("jpg|gif|png|jpeg")]
public HttpPostedFileBase PhotoUrl { get; set; }
below is the code somehow client side validation is not working...I searched couple of questions in this forum and wrote this..
here is the custom validation attribute "startDateAttribute"
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class StartDateAttribute : ValidationAttribute, IClientValidatable
{
public StartDateAttribute ()
{
}
public override bool IsValid(object value)
{
var date = (DateTime)value;
if (date.Date >= DateTime.Now.Date)
{
return true;
}
return false;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage,
ValidationType = "DateRange"
};
}
}
[CurrentDateAttribute(ErrorMessage = "select the correct date")]
public DateTime? StartDate { get; set; }
here is the JQuery code added
jQuery.validator.addMethod('DateRange', function (value, element, params) {
var d = new Date();
var currentDate = (d.getMonth()+1) + "/"+d.getDate()+ "/" + d.getFullYear() ;
return value >= currentDate;
});
// and an unobtrusive adapter
jQuery.validator.unobtrusive.adapters.add('DateRange', { }, function (options) {
options.rules['DateRange'] = true;
options.messages['DateRange'] = options.message;
});
One of the requirements of client side validation is that the ValidationType and the adapter name should match and should be lower case.
Change the ValidationType and adapter name to 'daterange' and check
For setting that I use Html helper method which is not the best imo, because I use static field.
public enum CurrentState
{
BeforeCurrent,
AfterCurrent
}
public static CurrentState currentState = CurrentState.BeforeCurrent;
public static MvcHtmlString ActiveActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName, bool checkAction = true)
{
string currentAction = helper.ViewContext.RouteData.GetRequiredString("action");
string currentController = helper.ViewContext.RouteData.GetRequiredString("controller");
if ((controllerName == currentController) && checkAction && (actionName == "Index"))
{
currentState = CurrentState.BeforeCurrent;
}
if ((controllerName == currentController) && checkAction && (actionName != currentAction))
{
if (currentState == CurrentState.BeforeCurrent)
{
return helper.ActionLink(linkText, actionName, controllerName, null, new { #class = "beforeCurrent" });
}
else if (currentState == CurrentState.AfterCurrent)
{
return helper.ActionLink(linkText, actionName, controllerName, null, new { #class = "afterCurrent" });
}
}
if ((controllerName == currentController) && (!checkAction || (actionName == currentAction)))
{
currentState = CurrentState.AfterCurrent;
return helper.ActionLink(linkText, actionName, controllerName, null, new { #class = "current" });
}
return helper.ActionLink(linkText, actionName, controllerName);
}
I have two levels of menus and that's why I use checkAction parameter:
main menu - #Html.ActiveActionLink(Resources.Global.mainMenuBoard, "Index", "Board", checkAction: false)
side menu - #Html.ActiveActionLink(#Resources.Global.managementOverview, "Index", "Management")
and in side menu I need to know if it's after and before current (overlapping items...).
Is it a way to improve that?
Additionally I must say that I use javascript also for that but it must work also for javascript disabled.
I finally solve that by generating whole menu in one helper:
public class Link
{
public string LinkText { get; set; }
public string ActionName { get; set; }
}
public static List<MvcHtmlString> SubMenuLinks(this HtmlHelper helper, string controllerName, List<Link> links)
{
List<MvcHtmlString> menuElements = new List<MvcHtmlString>();
string actualCssClass = "beforeCurrent";
string currentAction = helper.ViewContext.RouteData.GetRequiredString("action");
string currentController = helper.ViewContext.RouteData.GetRequiredString("controller");
foreach (Link link in links)
{
if (controllerName == currentController && link.ActionName == currentAction)
{
menuElements.Add(helper.ActionLink(link.LinkText, link.ActionName, controllerName, null, new { #class = "current" }));
actualCssClass = "afterCurrent";
}
else
{
menuElements.Add(helper.ActionLink(link.LinkText, link.ActionName, controllerName, null, new { #class = actualCssClass }));
}
}
return menuElements;
}
and in view:
#{
List<MvcHtmlString> actionMenu = Html.SubMenuLinks("Manager", new List<Link>()
{
new Link() { LinkText = "linkText", ActionName = "actionName" },
new Link() { LinkText = "linkText2", ActionName = "actionName2" }
});
}
#section SideMenu
{
#for (int i = 0; i < actionMenu.Count; i++)
{
<li id="menu#(i)">#actionMenu.ElementAt(i)</li>
}
}
Not perfect, but it works at least.