locked
Remove text in entry after "Send" command RRS feed

  • Question

  • User390469 posted

    Following this tutorial, I've made a simple chat app in Xamarin Forms. Only problem is, once I tap the send button and the new message is added to the list, the text inside the Entry/Editor doesn't disappear. Now in the code TextToSend = string.Empty; should be working but it doesn't, all it does is stop me from sending the text that's already in the entry twice. How can I fix it so that the text disappears once I hit send?

    ChatPage.xaml ```

            <!--Chat Entry-->
            <renderers:RoundedEntry Text="{Binding TextToSend}" 
                                    x:Name="ChatEntry"
                                    Placeholder="Type your message"
                                    CornerRadius="30"
                                    BackColor="White"
                                    BackgroundColor="Transparent"
                                    BorderColor="#999999"
                                    BorderWidth="5"
                                    FontSize="16"
                                    PlaceholderColor="#b3b3b3"
                                    Keyboard="Chat"
                                    WidthRequest="280"/>
    
            <!--Send Button-->
            <pancake:PancakeView x:Name="sendBtn" 
                                 BackgroundColor="#0f8df4"
                                 CornerRadius="100"
                                 xamEffects:TouchEffect.Color="White"
                                 xamEffects:Commands.Tap="{Binding SendCommand}"
                                 HeightRequest="47"
                                 WidthRequest="47"
                                 HorizontalOptions="EndAndExpand"
                                 VerticalOptions="Center">
    
                <Image Source="sendarrow1.png"
                       HeightRequest="30"
                       WidthRequest="30"
                       Margin="5,0,0,0"
                       HorizontalOptions="Center"
                       VerticalOptions="Center"/>
            </pancake:PancakeView>
        </StackLayout>
    

    ```

    ChatPageViewModel.cs ``` public class ChatbotPageViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// A collection.list of chat message items
        /// </summary>
        public ObservableCollection<ChatMessageModel> Messages { get; set; } = new ObservableCollection<ChatMessageModel>();
    
        /// <summary>
        /// The text that the user inputs
        /// </summary>
        public string TextToSend { get; set; }
    
        /// <summary>
        /// 
        /// </summary>
        public System.Action RefreshScrollDown;
    
        /// <summary>
        /// A command for sending the users messages
        /// </summary>
        public ICommand SendCommand { get; set; }
    
    
        /// <summary>
        /// ChatPageViewModel Constructor
        /// </summary>
        public ChatbotPageViewModel()
        {
            Messages.Add(new ChatMessageModel() { Text = "Hi" });
            Messages.Add(new ChatMessageModel() { Text = "How are you?" });
    
            SendCommand = new RelayCommand(Send);
        }
    
        /// <summary>
        /// This function sends a message
        /// </summary>
        private void Send()
        {
            if (!string.IsNullOrEmpty(TextToSend))
            {
                //This adds the following to the messages collection
                Messages.Add(new ChatMessageModel() { Text = TextToSend, User = App.User});
                TextToSend = string.Empty;
            }
        }
    }
    

    ```

    Sunday, November 24, 2019 6:35 PM

Answers

  • User89714 posted

    @jojo1234

    ChatbotPageViewModel may be inheriting from BaseViewModel, but it is not actually making use of it.

    Check the warnings when you build your solution, and clean up the code as appropriate

    For example, you have a PropertyChanged defined in ChatbotPageViewModel that is going to be hiding the one in BaseViewModel. Get rid of the one in ChatbotPageViewModel.

    Also, you have if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("TextToSend")); } in ChatbotPageViewModel, whereas you could/should simply call OnPropertyChanged();

    Also, hard-coding property names such as in PropertyChangedEventArgs("TextToSend") is prone to error. If you really need to specify a property name, use nameof(TextToSend). However, in this particular case, changing to use OnPropertyChanged() (see above) means that you don’t need to specify the name at all.

    If sorting out those points doesn't resolve it, post the updated XAML/C# afterwards.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, November 26, 2019 11:31 AM

All replies

  • User89714 posted

    @jojo1234

    The setters in your view model need to raise the PropertyChanged event when set is called with a value different to the current value.

    Also, make your binding to TextToSend a TwoWay binding.

    See https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/data-bindings-to-mvvm

    Sunday, November 24, 2019 6:52 PM
  • User390469 posted

    @JohnHardman said: @jojo1234

    The setters in your view model need to raise the PropertyChanged event when set is called with a value different to the current value.

    Also, make your binding to TextToSend a TwoWay binding.

    See https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/data-bindings-to-mvvm

    Okay, I've tried both of these and still got no effect. For the setters, I'm inheriting from a BaseViewModel that implements an INotifyPropertyChanged using [CallerMemberName], so I'm not sure if it's still necessary.

    Monday, November 25, 2019 10:44 PM
  • User89714 posted

    @jojo1234 said:

    @JohnHardman said: @jojo1234

    The setters in your view model need to raise the PropertyChanged event when set is called with a value different to the current value.

    Also, make your binding to TextToSend a TwoWay binding.

    See https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/data-bindings-to-mvvm

    Okay, I've tried both of these and still got no effect. For the setters, I'm inheriting from a BaseViewModel that implements an INotifyPropertyChanged using [CallerMemberName], so I'm not sure if it's still necessary.

    Post your updated code and markup

    Monday, November 25, 2019 11:14 PM
  • User390469 posted

    ChatViewModel.cs ``` using BluePillApp.Models; using BluePillApp.ViewModels.Base; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Text; using System.Windows.Input; using Xamarin.Forms;

    namespace BluePillApp.ViewModels { ///

    /// View model for the ChatbotPage.xaml /// public class ChatbotPageViewModel : BaseViewModel { public event PropertyChangedEventHandler PropertyChanged; private string _texttosend;

        /// <summary>
        /// A collection.list of chat message items
        /// </summary>
        public ObservableCollection<ChatMessageModel> Messages { get; set; } = new ObservableCollection<ChatMessageModel>();
    
        /// <summary>
        /// The text that the user inputs
        /// </summary>
        public string TextToSend
        {
            get
            {
                return _texttosend;
            }
    
            set
            {
                if (_texttosend != value)
                {
                    _texttosend = value;
    
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("TextToSend"));
                    }
                }
            }
        }
    
        /// <summary>
        /// A command for sending the users messages
        /// </summary>
        public ICommand SendCommand { get; set; }
    
    
        /// <summary>
        /// ChatPageViewModel Constructor
        /// </summary>
        public ChatbotPageViewModel()
        {
            Messages.Add(new ChatMessageModel() { Text = "Hi" });
            Messages.Add(new ChatMessageModel() { Text = "How are you?" });
    
            SendCommand = new RelayCommand(Send);
        }
    
        /// <summary>
        /// This function sends a message
        /// </summary>
        private void Send()
        {
            if (!string.IsNullOrEmpty(TextToSend))
            {
                //This adds the following to the messages collection
                Messages.Add(new ChatMessageModel() { Text = TextToSend, User = App.User});
                TextToSend = string.Empty;
            }
        }
    }
    

    }

    **BaseViewModel.cs** public class BaseViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName]string property = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
        }
    }
    

    For the .xaml I only changed this;

    <Grid RowSpacing="0" ColumnSpacing="0">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="1"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
    
        <!--Chat Views-->
    
        <!--Chat Messages Area-->
        <renderers:AutoScrollListView x:Name="messagesListView" 
                  Grid.Row="1" 
                  ItemTemplate="{StaticResource MessageTemplateSelector}" 
                  ItemsSource="{Binding Messages}" 
                  Margin="0" 
                  HasUnevenRows="True" 
                  VerticalOptions="FillAndExpand" 
                  SeparatorColor="Transparent"
                  SelectionMode="None">
        </renderers:AutoScrollListView>
    
        <!--A simple separater-->
        <BoxView BackgroundColor="LightGray"
                 HorizontalOptions="FillAndExpand"
                 Grid.Row="2"/>
    
    
        <!--Chat Entry and Send Button-->
        <StackLayout Grid.Row="3" Padding="5,10,10,10" Margin="0">
            <Grid ColumnSpacing="0" RowSpacing="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="5*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
    
                <!--Chat Entry-->
                <renderers:RoundedEntry x:Name="ChatEntry"
                                        Text="{Binding TextToSend, Mode=TwoWay}" 
                                        Grid.Column="0"
                                        Placeholder="Type your message"
                                        CornerRadius="30"
                                        BackColor="White"
                                        BackgroundColor="Transparent"
                                        BorderColor="#999999"
                                        BorderWidth="6"
                                        FontSize="16"
                                        PlaceholderColor="#b3b3b3"
                                        Keyboard="Chat"/>
    
                <!--Send Button-->
                <pancake:PancakeView x:Name="sendBtn" 
                                     Grid.Column="1"
                                     BackgroundColor="#0f8df4"
                                     CornerRadius="100"
                                     xamEffects:TouchEffect.Color="White"
                                     xamEffects:Commands.Tap="{Binding SendCommand}"
                                     HeightRequest="47"
                                     WidthRequest="47"
                                     VerticalOptions="Center"
                                     HorizontalOptions="End">
    
                    <Image Source="sendarrow1.png"
                       HeightRequest="30"
                       WidthRequest="30"
                       Margin="5,0,0,0"
                       HorizontalOptions="Center"
                       VerticalOptions="Center"/>
                </pancake:PancakeView>
            </Grid>
        </StackLayout>
    
    
    
        <!--Chatbot Header and Back Button-->
        <pancake:PancakeView BackgroundColor="#f7f7f7" Grid.Row="0" HasShadow="True" Padding="0,10,0,10">
            <StackLayout Orientation="Horizontal">
    
                <!--Back Arrow Button-->
                <renderers:FontAwesomeIcon Text="{x:Static helpers:IconsFA.BackArrow}" 
                                           HorizontalOptions="Start"
                                           TextColor="Black"
                                           FontSize="20"
                                           VerticalTextAlignment="Center"
                                           Margin="15,0,0,0">
                    <Label.GestureRecognizers>
                        <TapGestureRecognizer Tapped="BacktoMain_Button"/>
                    </Label.GestureRecognizers>
                </renderers:FontAwesomeIcon>
    
                <!--Fleming Image-->
                <StackLayout Orientation="Horizontal">
                    <Frame BackgroundColor="Gray" 
                           Padding="0" 
                           CornerRadius="100"
                           HasShadow="False"
                           IsClippedToBounds="True"
                           HeightRequest="40"
                           WidthRequest="40">
    
                        <Image HorizontalOptions="Center"
                               VerticalOptions="Center"/>
                    </Frame>
    
                    <!--Fleming Text-->
                    <Label Text="Fleming"
                           TextColor="Black"
                           FontAttributes="Bold"
                           FontSize="18"
                           VerticalOptions="Center"/>
                </StackLayout>
            </StackLayout>
        </pancake:PancakeView>
    </Grid>
    

    ```

    Monday, November 25, 2019 11:42 PM
  • User89714 posted

    @jojo1234

    Can you re-post, to show the entirety of ChatViewModel.cs (you've chopped the top of the class off), and to show your XAML (you've posted the BaseViewModel.cs twice instead).

    Monday, November 25, 2019 11:51 PM
  • User390469 posted

    @JohnHardman My bad, I've edited the above comment

    Monday, November 25, 2019 11:59 PM
  • User89714 posted

    @jojo1234

    ChatbotPageViewModel may be inheriting from BaseViewModel, but it is not actually making use of it.

    Check the warnings when you build your solution, and clean up the code as appropriate

    For example, you have a PropertyChanged defined in ChatbotPageViewModel that is going to be hiding the one in BaseViewModel. Get rid of the one in ChatbotPageViewModel.

    Also, you have if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("TextToSend")); } in ChatbotPageViewModel, whereas you could/should simply call OnPropertyChanged();

    Also, hard-coding property names such as in PropertyChangedEventArgs("TextToSend") is prone to error. If you really need to specify a property name, use nameof(TextToSend). However, in this particular case, changing to use OnPropertyChanged() (see above) means that you don’t need to specify the name at all.

    If sorting out those points doesn't resolve it, post the updated XAML/C# afterwards.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Tuesday, November 26, 2019 11:31 AM
  • User390469 posted

    This worked for me perfectly, thank you

    Thursday, November 28, 2019 8:10 PM