Bruno
Bruno

Reputation: 59

WPF TextBlock Binding to a String

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

Answers (3)

Ivan Vasiljevic
Ivan Vasiljevic

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

denys-vega
denys-vega

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

O. R. Mapper
O. R. Mapper

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:

  • 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.

Upvotes: 0

Related Questions