Reputation: 59
I want to bind a TextBlock to a string which takes its value from a txt file. The string is correctly filled but its contents are not displayed.
Class file:
public partial class JokesMessageBox : Window
{
public JokesMessageBox()
{
InitializeComponent();
}
public string Joke { get; set; }
public string path = "data/jokes.txt";
public void ReadFile(string path)
{
Joke = File.ReadAllText(path);
}
}
XAML:
<TextBlock HorizontalAlignment="Left" Margin="22,10,0,0"
TextWrapping="Wrap" Text="{Binding Joke}" VerticalAlignment="Top"
Height="60" Width="309"/>
EDIT:
In the MainWindow class:
private void btnJokesFirstScreen_Click_1(object sender, RoutedEventArgs e)
{
JokesMessageBox jkb = new JokesMessageBox();
jkb.Show();
jkb.ReadFile("data/jokes.txt");
}
I spent 3+ hours on google, youtube, MSDN, StackOverflow and still can't get it working. What am I missing?
Upvotes: 4
Views: 26686
Reputation: 5708
Your class is not implementing INotifyPropertyChanged interface. So when you change property Joke TextBlock is not updated. I would do something like this:
public partial class JokesMessageBox : Window, INotifyPropertyChanged
{
public JokesMessageBox()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
public string Joke { get; set; }
public string path = "data/jokes.txt";
public void ReadFile(string path)
{
Joke = File.ReadAllText(path);
OnPropertyChanged("Joke");
}
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I would also suggest you to read about MVVM patern.
Upvotes: 0
Reputation: 3697
If the you need to update the binding, the property Joke
must be a DependencyProperty
or the Windows
must implement INotifyPropertyChanged
interface.
On the view, the binding needs to know Source
.
Example #1 (Using DependencyProperty
):
public partial class JokesMessageBox : Window
{
public JokesMessageBox()
{
InitializeComponent();
ReadFile(Path); //example call
}
public string Joke
{
get { return (string)GetValue(JokeProperty); }
set { SetValue(JokeProperty, value); }
}
public static readonly DependencyProperty JokeProperty =
DependencyProperty.Register("Joke", typeof(string), typeof(JokesMessageBox), new PropertyMetadata(null));
public const string Path = "data/jokes.txt";
public void ReadFile(string path)
{
Joke = File.ReadAllText(path);
}
}
Example #2 (Using INotifyPropertyChanged
interface):
public partial class JokesMessageBox : Window, INotifyPropertyChanged
{
public JokesMessageBox()
{
InitializeComponent();
ReadFile(Path); //example call
}
private string _joke;
public string Joke
{
get { return _joke; }
set
{
if (string.Equals(value, _joke))
return;
_joke = value;
OnPropertyChanged("Joke");
}
}
public const string Path = "data/jokes.txt";
public void ReadFile(string path)
{
Joke = File.ReadAllText(path);
}
//INotifyPropertyChanged members
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
And the view (XAML partial):
...
<TextBlock HorizontalAlignment="Left" Margin="22,10,0,0"
TextWrapping="Wrap"
Text="{Binding Joke,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"
VerticalAlignment="Top"
Height="60" Width="309"/>
...
I hope it helps.
Upvotes: 10
Reputation: 20722
When you read the contents of the file, you assign the read string to your Joke
property:
Joke = File.ReadAllText(path);
The Text
property of the TextBlock
is indeed bound to that property (if you have properly set the data context):
Text="{Binding Joke}"
However, what is missing is that the binding cannot possibly have any idea that the property value has changed. You need to issue a notification about the property change.
There are two ways to do this that will be recognized by WPF bindings:
Joke
property as a dependency property. This is based on some WPF infrastructure that automatically issues the change notifications.INotifyPropertyChanged
interface. Here, you have to implement a simple interface with a PropertyChanged
event, which you have to fire in your property setter while passing the name of the property as a string.Upvotes: 0