Frantisek Pastorek Frantisek Pastorek - 1 month ago 8
C# Question

binding not working in another class

textBox binding logContent in another class.
If i change value of variable logContent in MainWindow all working right. But if i change value of variable logContent in Test.cs (when i click on button) it is not working.

MainWindow.cs

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
textBox.DataContext = Log.Instance;
Log.Instance.logContent += "aaa" + Environment.NewLine; //this working
}

private void button_Click(object sender, RoutedEventArgs e)
{
Test.Instance.Volaj();
}
}


Log.cs

class Log
{
public string logContent { get; set; }

private static Log instance;
public static Log Instance
{
get
{
if (instance == null)
{
instance = new Log();
}
return instance;
}
}
}


Test.cs

class Test
{
private static Test instance;
public static Test Instance
{
get
{
if (instance == null)
{
instance = new Test();
}
return instance;
}
}

public void Volaj()
{
Log.Instance.logContent += "bbb" + Environment.NewLine; //not working
}
}


XAML of textBox

<TextBox
x:Name="textBox"
HorizontalAlignment="Left"
Height="154"
Margin="10,155,0,0"
TextWrapping="Wrap"
Text="{Binding logContent}"
VerticalAlignment="Top"
Width="497"/>

Answer

in your code, the DataBinding is not working in any class.

You can see this with this simple test (you have to add the Loaded-Event in the MainWindow.xaml):

public MainWindow()
{
    InitializeComponent();
    textBox.DataContext = Log.Instance;
    Debug.WriteLine($"Text [ctor before change]: {textBox.Text}");
    // Output:
    Log.Instance.logContent += "aaa" + Environment.NewLine; //this working
    Debug.WriteLine($"Text [ctor after change]: {textBox.Text}");
    // Output:
}

private void button_Click(object sender, RoutedEventArgs e)
{
    Test.Instance.Volaj();
}

private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
    Debug.WriteLine($"Text [Loaded before change]: {textBox.Text}");
    // Output: aaa
    Log.Instance.logContent += "bbb" + Environment.NewLine;
    Debug.WriteLine($"Text [Loaded after change]: {textBox.Text}");
    // Output: aaa
}

The TextBox.Text Property does not change during the constructor. After the constructor is finished, the view reads the DataContext once and updates its Text property. That's why you see the text in your TextBox. When the Loaded-Event is fired, the TextBox already has the text-value. Other changes will not be displayed.

To make the binding work, you have to notify the view, that a property has changed. The INotifyPropertyChanged-Interface exists for this reason. So if you change your Log.cs to the following, it should work:

class Log : INotifyPropertyChanged
{
    private string _logContent;

    public string logContent
    {
        get { return _logContent; }
        set { _logContent = value; OnPropertyChanged(); }
    }

    private static Log instance;
    public static Log Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Log();
            }
            return instance;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
Comments