Commit 363d5a57 by Javier Piris

Creados y añadido modelo nuevo de datos + CustomCells nuevas, un selector…

Creados y añadido modelo nuevo de datos + CustomCells nuevas, un selector template y la adaptación para la vista de nueva consulta + Adaptación delos viewmodels de preguntas al nuevo modelo
parent 88f1509e
using MvvmHelpers;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
namespace inutralia.Models.Questions
{
[JsonObject(MemberSerialization.OptIn)]
[DataPath("messages")]
public class Message : ObservableEntityData
{
public enum Estatus
{
Pending,
Answered_for_client,
Answered_for_nutricionist,
Closed
}
public string StatusImg => imgStatus[StateId];
[JsonProperty("text", Required = Required.Always)]
public string Text
{
get { return _text; }
set { SetProperty(ref _text, value); }
}
string _text;
[JsonProperty("datetime", Required = Required.Always)]
public DateTime MessageDateTime
{
get { return _messageDateTime; }
set { SetProperty(ref _messageDateTime, value); }
}
DateTime _messageDateTime;
public string TimeDisplay => MessageDateTime.ToLocalTime().ToString();
[JsonProperty("isText", Required = Required.Always)]
public bool IsTextIn
{
get { return _isTextIn; }
set { SetProperty(ref _isTextIn, value); }
}
bool _isTextIn;
[JsonProperty("state_id", Required = Required.Always)]
public int StateId { get; set; }
[JsonProperty("status", Required = Required.Always)]
[JsonConverter(typeof(StringEnumConverter))]
public Estatus State { get; set; }
[JsonProperty("subject", Required = Required.Always)]
public string Subject
{
get { return _subject; }
set { SetProperty(ref _subject, value); }
}
string _subject;
string[] imgStatus = new string[2]
{
"pendiente.png", // 1 - Pendiente de responder
//"respondida_por_cliente.png", // 2 - Respondida por cliente
//"respondida_por_nutricionista", // 3- Respondida por nutricionista
"cerrada" // 4 - Conversación cerrada
};
}
}
\ No newline at end of file
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Questions\Message.cs" />
<Compile Include="Utils\BoolConverter.cs" /> <Compile Include="Utils\BoolConverter.cs" />
<Compile Include="Menu\LocalMenu.cs" /> <Compile Include="Menu\LocalMenu.cs" />
<Compile Include="Menu\MenuBase.cs" /> <Compile Include="Menu\MenuBase.cs" />
...@@ -37,8 +38,6 @@ ...@@ -37,8 +38,6 @@
<Compile Include="Profile\Profile.cs" /> <Compile Include="Profile\Profile.cs" />
<Compile Include="Menu\Ingredient.cs" /> <Compile Include="Menu\Ingredient.cs" />
<Compile Include="Menu\Menu.cs" /> <Compile Include="Menu\Menu.cs" />
<Compile Include="Questions\QuestionMessage.cs" />
<Compile Include="Questions\QuestionSpecialist.cs" />
<Compile Include="Recipe\Recipe.cs" /> <Compile Include="Recipe\Recipe.cs" />
<Compile Include="Recipe\RecipeOption.cs" /> <Compile Include="Recipe\RecipeOption.cs" />
<Compile Include="Recipe\RecipeOptionGroup.cs" /> <Compile Include="Recipe\RecipeOptionGroup.cs" />
......
using inutralia.CustomCells;
using inutralia.Models.Questions;
using Xamarin.Forms;
namespace inutralia
{
public class SelectorDataTemplate : DataTemplateSelector
{
private readonly DataTemplate textInDataTemplate;
private readonly DataTemplate textOutDataTemplate;
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
var messageVm = item as Message;
if (messageVm == null)
return null;
return messageVm.IsTextIn ? this.textInDataTemplate : this.textOutDataTemplate;
}
public SelectorDataTemplate()
{
this.textInDataTemplate = new DataTemplate(typeof(TextInViewCell));
this.textOutDataTemplate = new DataTemplate(typeof(TextOutViewCell));
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="inutralia.CustomCells.TextInViewCell">
<Grid ColumnSpacing="2" Padding="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Frame Grid.Row="0" Grid.Column="1" BackgroundColor="#0535f0" CornerRadius="15">
<Frame.HasShadow>
<OnPlatform x:TypeArguments="x:Boolean" iOS="false" Android="true"/>
</Frame.HasShadow>
<StackLayout>
<Label TextColor="White" Text="{Binding Text}" />
</StackLayout>
</Frame>
<Label FontSize="Micro" Grid.Row="1" Grid.Column="1" Text="{Binding MessageDateTime, StringFormat='{0:MM/dd/yyyy hh:mm tt}'}" TextColor="Gray"></Label>
</Grid>
</ViewCell>
\ No newline at end of file
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace inutralia.CustomCells
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class TextInViewCell : ViewCell
{
public TextInViewCell()
{
InitializeComponent();
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="inutralia.CustomCells.TextOutViewCell">
<Grid ColumnSpacing="2" Padding="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="2"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Frame Grid.Row="0" Grid.Column="1" CornerRadius="15">
<Frame.HasShadow>
<OnPlatform x:TypeArguments="x:Boolean" Android="true" iOS="True"/>
</Frame.HasShadow>
<Frame.BackgroundColor>
<OnPlatform x:TypeArguments="Color" Android="White" iOS="#F5F5F5"/>
</Frame.BackgroundColor>
<StackLayout>
<Label TextColor="Black" Text="{Binding Text}" />
</StackLayout>
</Frame>
<Label Grid.Row="1" FontSize="Micro" Grid.Column="1" HorizontalTextAlignment="End" Text="{Binding MessageDateTime, StringFormat='{0:MM/dd/yyyy hh:mm tt}'}" TextColor="Gray"></Label>
</Grid>
</ViewCell>
\ No newline at end of file
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace inutralia.CustomCells
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class TextOutViewCell : ViewCell
{
public TextOutViewCell()
{
InitializeComponent();
}
}
}
\ No newline at end of file
using inutralia.Models; using inutralia.Models.Questions;
using MvvmHelpers; using MvvmHelpers;
using System.Collections.Generic; using System;
using System.Linq; using System.Windows.Input;
using System.Net.Http;
using System.Threading.Tasks;
using Xamarin.Forms; using Xamarin.Forms;
namespace inutralia.ViewModels namespace inutralia.ViewModels
{ {
public class NewQuestionViewModel : BaseNavigationViewModel public class NewQuestionViewModel : BaseViewModel
{ {
public enum Estatus public ObservableRangeCollection<Message> ListMessages { get; }
{ public ICommand SendCommand { get; set; }
Pending,
Answered_for_client,
Answered_for_nutricionist,
Closed
}
public QuestionSpecialist QuestionSpecialist { private set; get; }
public Estatus State => (Estatus)QuestionSpecialist?.Id;
public ObservableRangeCollection<QuestionMessage> _NewQuestion;
// Comando de update del listado
Command _RefreshNewQuestionCommand;
// Comando de borrado de elemento
Command _DeleteNewQuestionCommand;
public NewQuestionViewModel(QuestionSpecialist quest)
{
QuestionSpecialist = quest;
Title = QuestionSpecialist.Subject;
if (quest.Messages.Count() > 0)
{
NewQuestion = new ObservableRangeCollection<QuestionMessage>(quest.Messages);
}
else
{
NewQuestion = new ObservableRangeCollection<QuestionMessage>();
}
}
// Acceso a la lista de PREGUNTAS
public ObservableRangeCollection<QuestionMessage> NewQuestion
{
// Getter (lazy load), crea la lista si no existe
get { return _NewQuestion ?? (_NewQuestion = new ObservableRangeCollection<QuestionMessage>()); }
// Setter. Cambia el valor y notifica a la vista de dicho cambio
set
{
_NewQuestion = value;
OnPropertyChanged("NewQuestion");
}
}
public async Task RefreshData()
{
if (QuestionSpecialist == null || (QuestionSpecialist.Id < 0))
return;
IsBusy = true;
if (await App.API.RefreshItemAsync(QuestionSpecialist))
{
Title = QuestionSpecialist.StatusImg;
OnPropertyChanged("State");
}
IsBusy = false;
await FetchQuestions();
}
///<summary> public NewQuestionViewModel()
/// Método que realiza la carga inicial del listado
///</summary>
public async Task ExecuteLoadNewQuestionCommand()
{ {
///Realiza el procesp de actualización si hay menos
///de un elemento en el listado
if (QuestionSpecialist.Messages.Count() < 1)
await FetchQuestions();
}
/// <summary> ListMessages = new ObservableRangeCollection<Message>();
/// Acceso al comando de actualización del listado
/// </summary>
public Command RefreshNewQuestionCommand
{
// Getter (lazy load), crea el comando si no existe
get { return _RefreshNewQuestionCommand ?? (_RefreshNewQuestionCommand = new Command(async () => await ExecuteRefreshQuestionMessagesCommand())); }
}
/// <summary> SendCommand = new Command(() =>
/// Proceso de ejecución del comando de actualización del listado
/// </summary>
public async Task ExecuteRefreshQuestionMessagesCommand()
{
try
{
// Hace que el comando no se pueda ejecutar de nuevo
RefreshNewQuestionCommand.ChangeCanExecute();
// Realiza el proceso de actualización
await FetchQuestions();
// Hace que el comando pueda volver a ejecutarse
RefreshNewQuestionCommand.ChangeCanExecute();
}
catch (System.Exception e)
{ {
string err = e.Message; if (!String.IsNullOrWhiteSpace(OutText))
}
}
///<summary>
///Proceso de actualización del listado
///</summary>
async Task FetchQuestions()
{
// Indicamos que estámos ocupados (provoca que aparezca el indicador de carga)
IsBusy = true;
// Llamada al API para coger el listado (provoca que se actualize la vista del listado)
try
{
if (await App.API.RefreshItemAsync(QuestionSpecialist) == true)
{ {
Title = QuestionSpecialist.Subject; var message = new Message
NewQuestion = new ObservableRangeCollection<QuestionMessage>(QuestionSpecialist.Messages); {
} Text = OutText,
} IsTextIn = false,
MessageDateTime = DateTime.Now
catch (System.Exception e) };
{
string err = e.Message;
NewQuestion.Clear();
}
// Indicamos que ya no estámos ocupados (provoca que desaparezca el indicador de carga)
IsBusy = false;
}
///<summary>
///Acceso al comando de borrado de pregunta
///</summary>
public Command DeleteQuestionCommand
{
// Getter (lazy load), crea el comando si no existe. Nótese que, a diferencia del comando
// de Refresh, éste recibe una notificación como parámetro
get
{
return _DeleteNewQuestionCommand ?? (_DeleteNewQuestionCommand = new Command(async (parameter) => await ExecuteDeleteQuestionCommand(parameter as QuestionMessage)));
}
}
///<summary>
///Proceso de ejecución de comando de borrado
///</summary>
///<param name="messag"></param>
///<returns></returns>
async Task ExecuteDeleteQuestionCommand(QuestionMessage messag)
{
// Verificar parámetro
if (messag != null)
{
// Indicamos que estámos ocupados (provoca que aparezca el indicador de carga)
IsBusy = true;
// Llamamos al API para borrar el mensaje
await App.API.DeleteItemAsync(messag);
//Actualizamos la lista
await FetchQuestions();
//Indicamos que no estámos ocupados (provoca que desarparezca el indicador de carga)
IsBusy = false;
}
}
///<summary>
///Guarda un mensaje perteneciente a QuestionSpecialist ya sea una pregunta nueva, nuevo mensaje o edición
///</summary>
///<param name="text"></param>
///<returns></returns>
public async Task SaveQuestion(string text)
{
var q = QuestionSpecialist;
HttpMethod method = HttpMethod.Post;
IsBusy = true; ListMessages.Add(message);
OutText = "";
if (q.Id < 0)
{
var data = new Dictionary<string, string>()
{
{"subject", q.Subject }, {"message", text}
};
// New Question
await App.API.RawMessage(method, string.Format("questions"), data, q);
}
else
{
QuestionMessage msg;
if (q.State == QuestionSpecialist.Estatus.Closed)
{
//Edit last Message
msg = q.Messages.Last();
method = HttpMethod.Put;
} }
else
{
//Add new Message
msg = new QuestionMessage();
} //endif
msg.Text = text;
await App.API.RawMessage(method, string.Format("questions/{0}", q.Id), msg, q);
} // endif
IsBusy = false;
NewQuestion = new ObservableRangeCollection<QuestionMessage>(QuestionSpecialist.Messages); });
} }
///<summary>
///Actualiza una pregunta
///</summary>
///<returns></returns>
public async Task SaveQuestion()
{
var q = QuestionSpecialist;
HttpMethod method = HttpMethod.Post;
IsBusy = true;
await App.API.UpdateItemAsync(q);
if (await App.API.RefreshItemAsync(QuestionSpecialist))
{
Title = QuestionSpecialist.StatusImg;
OnPropertyChanged("State");
}
IsBusy = false; public string OutText
{
get { return _outText; }
set { SetProperty(ref _outText, value); }
} }
string _outText = string.Empty;
public bool IsCloseOrPending => (State == Estatus.Answered_for_client || State == Estatus.Answered_for_nutricionist || State == Estatus.Pending || State == Estatus.Closed) && QuestionSpecialist.Messages.Count() > 0 || State == Estatus.Answered_for_nutricionist;
public bool MayBeClosed => !IsCloseOrPending;
} }
} }
using System.Threading.Tasks; using System.Threading.Tasks;
using inutralia.Models; using inutralia.Models;
using inutralia.Models.Questions;
namespace inutralia.ViewModels namespace inutralia.ViewModels
{ {
...@@ -13,31 +14,31 @@ namespace inutralia.ViewModels ...@@ -13,31 +14,31 @@ namespace inutralia.ViewModels
Cerrado = 4 Cerrado = 4
} }
public PendingReadViewModel(QuestionSpecialist questionSpecialist) public PendingReadViewModel(Message message)
{ {
QuestionSpecialist = questionSpecialist; Message = message;
Title = QuestionSpecialist?.StatusImg; Title = message?.StatusImg;
} }
public PendingReadViewModel() { } public PendingReadViewModel() { }
public QuestionSpecialist QuestionSpecialist { private set; get; } public Message Message { private set; get; }
public int StateId => QuestionSpecialist.StateId; public int StateId => Message.StateId;
public Estatus estatus => (Estatus)QuestionSpecialist?.StateId; public Estatus estatus => (Estatus)Message?.StateId;
public async Task RefresData() public async Task RefresData()
{ {
if (QuestionSpecialist == null) if (Message == null)
return; return;
IsBusy = true; IsBusy = true;
if (await App.API.RefreshItemAsync(QuestionSpecialist)) if (await App.API.RefreshItemAsync(Message))
{ {
Title = QuestionSpecialist.StatusImg; Title = Message.StatusImg;
OnPropertyChanged(""); OnPropertyChanged("");
} }
......
using inutralia.Models; using inutralia.Models;
using inutralia.Models.Questions;
using MvvmHelpers; // Este namespace está en el paquete Refractored.MvvmHelpers using MvvmHelpers; // Este namespace está en el paquete Refractored.MvvmHelpers
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
...@@ -14,7 +15,7 @@ namespace inutralia.ViewModels ...@@ -14,7 +15,7 @@ namespace inutralia.ViewModels
public QuestionListViewModel() { } public QuestionListViewModel() { }
// Datos del histórico // Datos del histórico
ObservableRangeCollection<QuestionSpecialist> _QuestionList; ObservableRangeCollection<Message> _QuestionList;
// Comando de loading del listado // Comando de loading del listado
Command _LoadQuestionListCommand; Command _LoadQuestionListCommand;
...@@ -23,10 +24,10 @@ namespace inutralia.ViewModels ...@@ -23,10 +24,10 @@ namespace inutralia.ViewModels
Command _RefreshQuestionListCommand; Command _RefreshQuestionListCommand;
// Acceso a la lista preguntas // Acceso a la lista preguntas
public ObservableRangeCollection<QuestionSpecialist> QuestionList public ObservableRangeCollection<Message> QuestionList
{ {
// Getter (lazy load), crea la lista si no exite // Getter (lazy load), crea la lista si no exite
get => _QuestionList ?? (_QuestionList = new ObservableRangeCollection<QuestionSpecialist>()); get => _QuestionList ?? (_QuestionList = new ObservableRangeCollection<Message>());
// Setter. Cambia el valor y notifica a la vista de dicho cambio // Setter. Cambia el valor y notifica a la vista de dicho cambio
set set
...@@ -97,7 +98,7 @@ namespace inutralia.ViewModels ...@@ -97,7 +98,7 @@ namespace inutralia.ViewModels
// la notificación (campo Body) // la notificación (campo Body)
try try
{ {
QuestionList = new ObservableRangeCollection<QuestionSpecialist>(await App.API.RefreshListAsync<QuestionSpecialist>()); QuestionList = new ObservableRangeCollection<Message>(await App.API.RefreshListAsync<Message>());
} }
catch (Exception e) catch (Exception e)
{ {
......
using inutralia.Models; using inutralia.Models;
using inutralia.Models.Questions;
using inutralia.ViewModels; using inutralia.ViewModels;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Xaml; using Xamarin.Forms.Xaml;
...@@ -18,7 +19,7 @@ namespace inutralia.Views.Question ...@@ -18,7 +19,7 @@ namespace inutralia.Views.Question
protected async void ItemTapped(object sender, ItemTappedEventArgs e) protected async void ItemTapped(object sender, ItemTappedEventArgs e)
{ {
var respon = e.Item as QuestionSpecialist; var respon = e.Item as Message;
if (respon.StatusImg == "Respondida") if (respon.StatusImg == "Respondida")
{ {
await DisplayAlert("ERROR", "La pregunta ya está respondida", "Entendido"); await DisplayAlert("ERROR", "La pregunta ya está respondida", "Entendido");
...@@ -28,7 +29,7 @@ namespace inutralia.Views.Question ...@@ -28,7 +29,7 @@ namespace inutralia.Views.Question
await Navigation.PushAsync( await Navigation.PushAsync(
new PendingReadView() new PendingReadView()
{ {
BindingContext = new PendingReadViewModel((QuestionSpecialist)e.Item) BindingContext = new PendingReadViewModel((Message)e.Item)
} }
); );
((ListView)sender).SelectedItem = null; ((ListView)sender).SelectedItem = null;
......
...@@ -2,181 +2,51 @@ ...@@ -2,181 +2,51 @@
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:artina="clr-namespace:UXDivers.Artina.Shared;assembly=UXDivers.Artina.Shared" xmlns:artina="clr-namespace:UXDivers.Artina.Shared;assembly=UXDivers.Artina.Shared"
xmlns:local="clr-namespace:inutralia"
x:Class="inutralia.Views.Question.NewConsultationView" x:Class="inutralia.Views.Question.NewConsultationView"
x:Name="newConsultationView" x:Name="newConsultationView"
Title="Nueva Consulta" Title="Nueva Consulta"
Icon="Add1" Icon="Add1"
BackgroundColor="{DynamicResource BasePageColor}" BackgroundColor="{DynamicResource BasePageColor}"
> NavigationPage.HasBackButton="True">
<ContentPage.Content> <ContentPage.Resources>
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"> <ResourceDictionary>
<StackLayout VerticalOptions="FillAndExpand" Margin="10,15,10,15"> <local:SelectorDataTemplate x:Key="MessageTemplateSelector"/>
<ListView ItemsSource="{Binding NewQuestion}" </ResourceDictionary>
ItemTapped="ItemTapped" </ContentPage.Resources>
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshNewQuestionCommand}"
IsRefreshing="{Binding IsBusy, Mode=TwoWay}"
BackgroundColor="Transparent"
CachingStrategy="RecycleElement"
Footer=""
HasUnevenRows="True"
x:Name="listNewConsultation">
<!--Aquí se configura el template para cada elemento de la lista-->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<!--Aquí comienza la definición visual de cada elemento de la lista. Se utiliza un Frame (implica borde redondeado)
dentro del cual va el icono con la notificación seguido del título de la misma-->
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand">
<Image Source="user_chat.png" VerticalOptions="CenterAndExpand" HorizontalOptions="Fill" IsVisible="{Binding FromUser}">
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double"
Phone="50"
Tablet="100"/>
</Image.WidthRequest>
<Image.HeightRequest>
<OnIdiom x:TypeArguments="x:Double"
Phone="50"
Tablet="100"/>
</Image.HeightRequest>
</Image>
<ContentView VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" IsVisible="{Binding FromUser}" BackgroundColor="{DynamicResource BasePageColor}">
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<StackLayout Style="{StaticResource ChatMessageEntryStyle}">
<Label Text="{Binding Text}" HorizontalOptions="StartAndExpand" TextColor="Black">
<Label.FontSize>
<OnIdiom x:TypeArguments="x:Double"
Phone="15"
Tablet="35"/>
</Label.FontSize>
</Label>
</StackLayout>
</StackLayout>
</ContentView>
<ContentView VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" IsVisible="{Binding FromExpert}" BackgroundColor="{DynamicResource BasePageColor}">
<StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<StackLayout Style="{StaticResource ChatMessageEntryStyle }">
<Label Text="{Binding Text}" HorizontalOptions="StartAndExpand" TextColor="Black">
<Label.FontSize>
<OnIdiom x:TypeArguments="x:Double"
Phone="15"
Tablet="35"/>
</Label.FontSize>
</Label>
</StackLayout>
</StackLayout>
</ContentView>
<Image Source="nutricionist_chat.png" VerticalOptions="CenterAndExpand" HorizontalOptions="Fill" IsVisible="{Binding FromExpert}">
<Image.WidthRequest>
<OnIdiom x:TypeArguments="x:Double"
Phone="50"
Tablet="100"/>
</Image.WidthRequest>
<Image.HeightRequest> <ContentPage.Content>
<OnIdiom x:TypeArguments="x:Double" <Grid RowSpacing="0" ColumnSpacing="0" >
Phone="50" <Grid.RowDefinitions>
Tablet="100"/> <RowDefinition Height="*"/>
</Image.HeightRequest> <RowDefinition Height="Auto" />
</Image> </Grid.RowDefinitions>
</StackLayout>
</ViewCell> <ScrollView>
</DataTemplate> <ListView x:Name="MessagesListView"
</ListView.ItemTemplate> ItemTemplate="{StaticResource MessageTemplateSelector}"
</ListView> ItemsSource="{Binding ListMessages}"
</StackLayout> HasUnevenRows="True"
SeparatorVisibility="None"
<StackLayout Orientation="Horizontal" VerticalOptions="End" Margin="10,0,10,0"> Footer=""
<Entry x:Name="newQuest" Placeholder="Escriba su pregunta" HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand"> />
</ScrollView>
<Entry.HeightRequest>
<OnIdiom x:TypeArguments="x:Double"> <StackLayout Orientation="Horizontal" Grid.Row="1" BackgroundColor="White" Padding="0,0,0,10">
<OnIdiom.Phone> <Entry HorizontalOptions="FillAndExpand"
<OnPlatform x:TypeArguments="x:Double" Placeholder=" Escriba aquí su mensaje"
iOS="40" Text="{Binding OutText}"
Android="48"/> Keyboard="Chat"
</OnIdiom.Phone> Margin="4"/>
<OnIdiom.Tablet> <Image Source="btn_enviar_chat.png" WidthRequest="45" HeightRequest="5" Margin="4" BackgroundColor="#FFA2C300">
<OnPlatform x:TypeArguments="x:Double" <Image.GestureRecognizers>
iOS="70" <TapGestureRecognizer
Android="65"/> Command="{Binding SendCommand}" />
</OnIdiom.Tablet> </Image.GestureRecognizers>
</OnIdiom> </Image>
</Entry.HeightRequest>
<Entry.FontSize>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>
<OnPlatform x:TypeArguments="x:Double"
iOS="25"
Android="17"/>
</OnIdiom.Phone>
<OnIdiom.Tablet>
<OnPlatform x:TypeArguments="x:Double"
iOS="40"
Android="40"/>
</OnIdiom.Tablet>
</OnIdiom>
</Entry.FontSize>
</Entry>
<artina:Button x:Name="buttonNewQuestion"
Image="btn_enviar_chat.png"
HorizontalOptions="End"
VerticalOptions="CenterAndExpand"
Style="{DynamicResource PrimaryActionButtonStyle}"
Clicked="ButtonNewQuestion_Clicked"
>
<Button.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>
<OnPlatform x:TypeArguments="x:Double"
iOS="40"
Android="48"/>
</OnIdiom.Phone>
<OnIdiom.Tablet>
<OnPlatform x:TypeArguments="x:Double"
iOS="70"
Android="65"/>
</OnIdiom.Tablet>
</OnIdiom>
</Button.HeightRequest>
<Button.WidthRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>
<OnPlatform x:TypeArguments="x:Double"
iOS="40"
Android="48"/>
</OnIdiom.Phone>
<OnIdiom.Tablet>
<OnPlatform x:TypeArguments="x:Double"
iOS="100"
Android="65"/>
</OnIdiom.Tablet>
</OnIdiom>
</Button.WidthRequest>
</artina:Button>
</StackLayout> </StackLayout>
</StackLayout> </Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>
\ No newline at end of file
...@@ -10,15 +10,26 @@ namespace inutralia.Views.Question ...@@ -10,15 +10,26 @@ namespace inutralia.Views.Question
[XamlCompilation(XamlCompilationOptions.Compile)] [XamlCompilation(XamlCompilationOptions.Compile)]
public partial class NewConsultationView : ContentPage public partial class NewConsultationView : ContentPage
{ {
protected NewQuestionViewModel ViewModel => BindingContext as NewQuestionViewModel; //protected NewQuestionViewModel ViewModel => BindingContext as NewQuestionViewModel;
NewQuestionViewModel vm;
public NewConsultationView() public NewConsultationView()
{ {
InitializeComponent(); InitializeComponent();
newQuest.IsEnabled = true;
buttonNewQuestion.IsEnabled = false;
buttonNewQuestion.Clicked += ButtonNewQuestion_Clicked; BindingContext = vm = new NewQuestionViewModel();
vm.ListMessages.CollectionChanged += (sender, e) =>
{
var target = vm.ListMessages[vm.ListMessages.Count - 1];
MessagesListView.ScrollTo(target, ScrollToPosition.End, true);
};
//newQuest.IsEnabled = true;
//buttonNewQuestion.IsEnabled = false;
//buttonNewQuestion.Clicked += ButtonNewQuestion_Clicked;
} }
//protected override void OnBindingContextChanged() //protected override void OnBindingContextChanged()
...@@ -32,28 +43,28 @@ namespace inutralia.Views.Question ...@@ -32,28 +43,28 @@ namespace inutralia.Views.Question
// OnDataRefreshed(); // OnDataRefreshed();
//} //}
private async void ButtonNewQuestion_Clicked(object sender, EventArgs e) //private async void ButtonNewQuestion_Clicked(object sender, EventArgs e)
{ //{
if (String.IsNullOrWhiteSpace(newQuest.Text)) // if (String.IsNullOrWhiteSpace(newQuest.Text))
{ // {
newQuest.Text = ""; // newQuest.Text = "";
return; // return;
} // }
await ViewModel.SaveQuestion(newQuest.Text); // await ViewModel.SaveQuestion(newQuest.Text);
listNewConsultation.SelectedItem = null; // listNewConsultation.SelectedItem = null;
//OnDataRefreshed(); // //OnDataRefreshed();
} //}
///// <summary> ///// <summary>
///// Método llamado cada vez que una página pasa a ser visible ///// Método llamado cada vez que una página pasa a ser visible
///// </summary> ///// </summary>
protected override async void OnAppearing() //protected override async void OnAppearing()
{ //{
base.OnAppearing(); // base.OnAppearing();
//await ViewModel.RefreshData(); // await ViewModel.RefreshData();
//OnDataRefreshed(); // OnDataRefreshed();
} //}
///// <summary> ///// <summary>
///// Método llamado al hacer tap en un elemento de la lista. Navega a la página de detalle ///// Método llamado al hacer tap en un elemento de la lista. Navega a la página de detalle
...@@ -61,22 +72,22 @@ namespace inutralia.Views.Question ...@@ -61,22 +72,22 @@ namespace inutralia.Views.Question
///// </summary> ///// </summary>
///// <param name="sender">La ListiView</param> ///// <param name="sender">La ListiView</param>
///// <param name="e">Argumentos del evento</param> ///// <param name="e">Argumentos del evento</param>
void ItemTapped(object sender, ItemTappedEventArgs e) //void ItemTapped(object sender, ItemTappedEventArgs e)
{ //{
if (e == null) return; // has been set to null, do not 'process' tapped event // if (e == null) return; // has been set to null, do not 'process' tapped event
QuestionMessage item = (QuestionMessage)e.Item; // QuestionMessage item = (QuestionMessage)e.Item;
if (ViewModel.NewQuestion.Last() == item && item.FromUser) // if (ViewModel.NewQuestion.Last() == item && item.FromUser)
{ // {
buttonNewQuestion.IsEnabled = true; // buttonNewQuestion.IsEnabled = true;
newQuest.IsEnabled = true; // newQuest.IsEnabled = true;
newQuest.Text = item.Text; // newQuest.Text = item.Text;
} // }
else // else
{ // {
((ListView)sender).SelectedItem = null; // de-select the row // ((ListView)sender).SelectedItem = null; // de-select the row
} // }
} //}
//private void OnDataRefreshed() //private void OnDataRefreshed()
//{ //{
......
using inutralia.Models; using inutralia.Models;
using inutralia.Models.Questions;
using inutralia.ViewModels; using inutralia.ViewModels;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Xaml; using Xamarin.Forms.Xaml;
...@@ -10,7 +11,7 @@ namespace inutralia.Views.Question ...@@ -10,7 +11,7 @@ namespace inutralia.Views.Question
{ {
protected PendingReadViewModel ViewModel => BindingContext as PendingReadViewModel; protected PendingReadViewModel ViewModel => BindingContext as PendingReadViewModel;
public QuestionSpecialist QuestionSpecialist { private set; get; } public Message Message { private set; get; }
public PendingReadView() public PendingReadView()
{ {
......
...@@ -37,6 +37,13 @@ ...@@ -37,6 +37,13 @@
<Compile Include="API\LocalDataService.cs" /> <Compile Include="API\LocalDataService.cs" />
<Compile Include="Converters\ImageTransformator.cs" /> <Compile Include="Converters\ImageTransformator.cs" />
<Compile Include="Converters\AlternatingBackgroundColorConverter.cs" /> <Compile Include="Converters\AlternatingBackgroundColorConverter.cs" />
<Compile Include="CustomCells\SelectorDataTemplate.cs" />
<Compile Include="CustomCells\TextInViewCell.xaml.cs">
<DependentUpon>TextInViewCell.xaml</DependentUpon>
</Compile>
<Compile Include="CustomCells\TextOutViewCell.xaml.cs">
<DependentUpon>TextOutViewCell.xaml</DependentUpon>
</Compile>
<Compile Include="Helpers\Settings.cs" /> <Compile Include="Helpers\Settings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="App.xaml.cs"> <Compile Include="App.xaml.cs">
...@@ -275,7 +282,6 @@ ...@@ -275,7 +282,6 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>
<None Include="SampleData.json" /> <None Include="SampleData.json" />
<None Include="Gorilla.json" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Views\Recipe\ItemList\RecipeItemTemplate.xaml"> <EmbeddedResource Include="Views\Recipe\ItemList\RecipeItemTemplate.xaml">
...@@ -480,6 +486,18 @@ ...@@ -480,6 +486,18 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="CustomCells\TextInViewCell.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="CustomCells\TextOutViewCell.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" /> <Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment