Home > Enterprise >  WPF PropertyChanged event not firing/updating textbox
WPF PropertyChanged event not firing/updating textbox

Time:10-08

I'm still relatively new to Data Binding in wpf, but despite plunging through all the articles and posts here and elsewhere about what could be wrong, I still have not found a solution. The code below is the prevalent information parsed out of my larger files.

I have made sure everything else is working, including adding a property to retrieve the protected parameter options to ensure options.FullPath is in fact getting set/changed on the Browse button's Click event. I attempted to subscribe to the PropertyChanged event in the main window with the line test.PropertyChanged = ShowMessage;, ShowMessage being a method that triggers a MessageBox with text in it. I tried multiple variations on the OnPropertyChanged method from hardcoding it within the calling method to what is displayed here. I even tried setting options to a default value of "" just in case it was being weird about that. No luck on anything, and I have no way to acquire C#6 at the moment, so it may very well be that what I have works with the right language updates, but I just can't tell since it doesn't trigger.

Any help or insight would be greatly appreciated!

Object Class:

public class EEOptionSet: INotifyPropertyChanged
{
    public EEOptionSet()
    {
    }
        
    public event PropertyChangedEventHandler PropertyChanged;

    private string _fullPath;

    public string FullPath
    {
        get { return _fullPath; }
        set
        {
            if (value != _fullPath)
            {
                _fullPath = value;
                OnPropertyChanged();
            }
        }
    }

    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }

}

Main window's code behind:

public partial class window : Window
{
    protected OptionSet options = new Option Set();

    private void BrowseFiles(object sender, RoutedEventArgs e)
    {
        options.FullPath = "Test";
    }
}

Textbox and Button instances in the xaml of my main window (extraneous properties like Grid placement, Alignment, etc removed for brevity):

<TextBox x:Name="FullPathText" Text="{Binding (options.FullPath), Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" IsReadOnly="True" Focusable="False"/>
<uc:ButtonExt x:Name="Browse" Content="..." Click="BrowseFiles"/>

NOTE: I have also tried:

Text="{Binding options.FullPath, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding Path=options.FullPath, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding Path=(_currentOptionSet.FullPath), Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"

As well as without the IsReadOnly and Focusable properties.

CodePudding user response:

  1. PropertyPath (this is the type of the Binding.Path property) can only be set by the path expression to the public property of the source. And your variable options is a protected field.

  2. If the source is not explicitly specified in the Binding (there are three ways of setting it: Source, ElementName and RelativeSource), then the Data Context of the element in which the binding is set is used for the source. You did not specify the source in any of these four ways.

An example of setting the Data Context and its use.
Written from assumption:

  • the EEOptionSet and the OptionSet classes - are one and the same, and you just made a mistake when copying the code;
  • the EEOptionSet class is declared in the same namespace as your window.
    <Window.DataContext>
        <local:EEOptionSet/>
    <Window.DataContext>
    protected readonly EEOptionSet options;
    public window()
    {
        InitializeComponent();

        options = (EEOptionSet) DataContext;
    }
    <TextBox Text="{Binding FullPath, Mode=OneWay}"
             IsReadOnly="True"
             Focusable="False"/>

CodePudding user response:

You cannot bind to a protected field.

Set the DataContext of the window to your field:

public partial class window : Window
{
    protected OptionSet options = new OptionSet();

    public window()
    {
        InitializeComponent();
        DataContext = options;
    }

    private void BrowseFiles(object sender, RoutedEventArgs e)
    {
        options.FullPath = "Test";
    }
}

...and remove "options" from the binding path(s) in the XAML markup:

Text="{Binding FullPath, UpdateSourceTrigger=PropertyChanged}"

Alternatively, make options a public property of the window and set the DataContext the the window itself:

public partial class window : Window
{
    public OptionSet options { get; private set; }

    public window()
    {
        InitializeComponent();
        options =  = new OptionSet();
        DataContext = this;
    }

    private void BrowseFiles(object sender, RoutedEventArgs e)
    {
        options.FullPath = "Test";
    }
}

Then you should keep the binding path as-is:

Text="{Binding options.FullPath, UpdateSourceTrigger=PropertyChanged}"
  • Related