My app has to load a .txt
file from the file system, read it and put its text into a TextBlock
, but I don't know how to connect my Button
to my view model so my text block that is bound to a property in it displays this text.
Let's repeat what I want my app to do:
.txt
fileNumbersString
propertyNumbersString
propertyI dont know how to get step 2 to work.
XAML
<Button Name="load" Background="Pink" Click="load_Click">Load File</Button>
<TextBox x:Name="numbers1" Text="{Binding NumbersString, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True"/>
Code-behind XAML
There is a mistake my view model property NumbersString
. It should be connected to the button.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new numbersViewModel();
}
public void load_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == true)
NumbersString = File.ReadAllText(openFileDialog.FileName);
}
}
View model
class numbersViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private numbersModel _model;
protected void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler evt = PropertyChanged;
if (evt != null)
evt(this, new PropertyChangedEventArgs(propertyName));
}
// iI want my text block to take the string from here
public string NumbersString
{
get { return _model.numbersString; }
set
{
if (value != _model.numbersString)
{
_model.numbersString = value;
RaisePropertyChanged("numbers1");
}
}
}
}
Model
private string model="";
public string numbersString
{
get
{
return model;
}
set
{
model = value;
}
}
You raise the property changed event for numbers1
in your NumbersString
property, therefore the change for the wrong property (that does not even exist) is triggered, but that will not update the TextBox
.
Adapt the property name in the call to RaisePropertyChanged
. You can use nameof
instead of a hardcoded string
.
public string NumbersString
{
get { return _model.numbersString; }
set
{
if (value != _model.numbersString)
{
_model.numbersString = value;
RaisePropertyChanged(nameof(NumbersString));
}
}
}
Since you are using a mix of code-behind and MVVM, you could set the NumbersString
property in your event handler like this:
public void load_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == true)
((numbersViewModel)DataContext).NumbersString = File.ReadAllText(openFileDialog.FileName);
}
The last bit to make it work is that you never create or assign an instance of a numbersModel
to the _model
property on numbersViewModel
. You could do that in the constructor.
public numbersViewModel(numbersModel numbersModel)
{
_model = numbersModel;
}
Instead of using event handlers for button clicks, you should use commands. You can copy the RelayCommand
class that @aepot linked . First, you create an ICommand
property in your numbersViewModel
.
public ICommand LoadFile { get; }
RelayCommand
implements the ICommand
interface and delegates the execution logic to a method that you have to pass when creating it in the constructor of numbersViewModel
:
public numbersViewModel(numbersModel numbersModel)
{
_model = numbersModel;
LoadFile = new RelayCommand(ExecuteLoadFile);
}
The ExecuteLoadFile
method contains the logic for loading the file and reading its text. In practice, this would also violate MVVM priciples as this method is located in a view model and OpenFileDialog
is a view type. You would extract this part into a service with an interface, so that the view model does not know about its implementation, but that is beyond the scope of this question.
private void ExecuteLoadFile(object obj)
{
var openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog().GetValueOrDefault())
NumbersString = File.ReadAllText(openFileDialog.FileName);
}
Finally, bind the Command
property on your button to the LoadFile
command.
<Button Name="load" Background="Pink" Content="Load File" Command="{Binding LoadFile}"/>
With these changes you can remove the event handler from your MainWindow
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.