This is my main body which handles the data. I invoke a command through XAML which should retrieve the data which is currently contained in the textbox in my xaml. When I try to print it or display it it doesn't work because it returns null.
namespace DoctorApplication.MVVM.ViewModel
{
internal class DataViewModel : ObservableObject
{
private string message;
public string Message
{
get { return message; }
set
{
message = value;
OnPropertyChanged();
}
}
public RelayCommand SendCommand { get; set; }
public BindableCollection<UserDataModel> users { get; set; }
public ObservableCollection<MessageModel> messages { get; set; }
public RelayCommand MessageCommand { get; set; }
public RelayCommand ConsoleLogcommand { get; set; }
private UserDataModel selectedUser;
public UserDataModel SelectedUser
{
get { return selectedUser; }
set
{
selectedUser = value;
OnPropertyChanged();
}
}
public DataViewModel()
{
users = new BindableCollection<UserDataModel>();
UserDataModel test1 = new UserDataModel("user1", "0612345678", 12345, 20, 80);
UserDataModel test2 = new UserDataModel("user2", "0698765432", 67890, 30, 70);
test1.AddMessage("Hello");
test1.AddMessage("I'm a console!");
test1.AddMessage("Goodbye!");
test2.AddMessage("Hi!");
test2.AddMessage("What's up?");
users.Add(test1);
users.Add(test2);
MessageCommand = new RelayCommand(DisplayInMessageBox);
SendCommand = new RelayCommand(DisplayInMessageBox);
}
public void DisplayInMessageBox(object message)
{
Console.WriteLine(message);
}
}
}
This is my XAML. It's a UserControl being displayed on my Main window.
<Grid Grid.Row="2" DockPanel.Dock="Bottom" Name="ChatTextBoxPanel">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<TextBox
Grid.Column="0"
Text="{Binding Message, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"
>
<TextBox.DataContext>
<m:DataViewModel/>
</TextBox.DataContext>
</TextBox>
<Button
Command="{Binding SendCommand}"
Background="#FF1B47F5"
BorderBrush="#FF1B1B1B"
Content="➤"
Foreground="#FFFFF7F7"
Grid.Column="1"
>
<Button.DataContext>
<m:DataViewModel/>
</Button.DataContext>
</Button>
</Grid>
And this is the relay command I use to invoke the command through XAML
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace DoctorApplication.Core
{
/* > The RelayCommand class implements the ICommand interface and is used to relay a command from the View to the
ViewModel */
internal class RelayCommand : ICommand
{
readonly Action<object> execute;
readonly Predicate<object> canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
{
throw new NullReferenceException("execute");
}
this.execute = execute;
this.canExecute = canExecute;
}
public RelayCommand(Action<object> execute) : this(execute, null)
{
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested = value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return canExecute == null ? true : canExecute(parameter);
}
public void Execute(object parameter)
{
execute.Invoke(parameter);
}
}
}
I would appreciate any tips on anything I can improve or anything that could possibly help in this situation as I am clueless to what I can change.
Update: By setting adding the command parameter as such:
CommandParameter="{Binding ElementName=ChatTextBox}"
I now receive the value of the text in the textbox but it now also include the following before the result (input: "test"): System.Windows.Controls.TextBox: test
Setting it toString() or (string) doesn't have any effect.
CodePudding user response:
Setting the DataContext
of the TextBox and the Button to two different view model instances is a programming error.
There should only be one assignment at the top level element of the view:
<Window ...>
<Window.DataContext>
<m:DataViewModel/>
</Window.DataContext>
<Grid Grid.Row="2" DockPanel.Dock="Bottom" Name="ChatTextBoxPanel">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<TextBox
Grid.Column="0"
Text="{Binding Message, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" />
<Button
Grid.Column="1"
Command="{Binding SendCommand}"
Background="#FF1B47F5" BorderBrush="#FF1B1B1B"
Foreground="#FFFFF7F7" Content="➤"/>
</Grid>
</Window>
Since the TextBox's Text property is bound to the Message property of the same view model object, the SendCommand
may directly access the Message
property.
public void DisplayInMessageBox(object p)
{
Console.WriteLine(Message);
}
CodePudding user response:
Solved it by adding the following parameter:
CommandParameter="{Binding Text, ElementName=ChatTextBox}"