4

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?

4
  • 1
    How/when is ReadFile called? Commented Mar 26, 2015 at 22:32
  • call readfile in constructor Commented Mar 26, 2015 at 22:33
  • I will recomend you to read a little about DataBinding. Commented Mar 26, 2015 at 22:35
  • I added where the ReadFile() is called. Commented Mar 26, 2015 at 22:41

3 Answers 3

10

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This worked! I went with the second example. After I had read this: link I thought it would be something quick and easy. Now I looked at the other similar problems other people had posted and I noticed this INotifyPropertyChanged interface. I'll look into it. Thanks!
0

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:

  • You declare your Joke property as a dependency property. This is based on some WPF infrastructure that automatically issues the change notifications.
  • You have your class implement the 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.

Comments

0

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.