I'm trying to bind the window title to the value of a property of a custom class. The issue is that the window's title is not updated when the property is updated.
The custom class:
public class ObservableWindowTitle : INotifyPropertyChanged
{
public string AppName { get; }
private string _currentFileName = string.Empty;
public string CurrentFileName
{
get => _currentFileName;
set
{
if (value is null)
{
throw new ArgumentNullException(nameof(value));
}
if (_currentFileName != value)
{
_currentFileName = value;
PropertyChanged?.Invoke(this, new(nameof(CurrentFileName)));
}
}
}
private bool _isUnsaved = false;
public bool IsUnsaved
{
get => _isUnsaved;
set
{
if (_isUnsaved != value)
{
_isUnsaved = value;
PropertyChanged?.Invoke(this, new(nameof(_isUnsaved)));
}
}
}
public string Title
{
get => string.Format("{0}{1} - {2}",
(IsUnsaved ? "*" : string.Empty),
(CurrentFileName.Length == 0 ? "Untitled" : CurrentFileName),
AppName);
}
public event PropertyChangedEventHandler? PropertyChanged;
public ObservableWindowTitle(string appName) => AppName = appName;
}
The Window Title XAML:
Title="{Binding Path=Title, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
The Window code:
public partial class MainWindow : Window
{
const string fileDialogFilter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
readonly ILogger<MainWindow> _logger;
ObservableWindowTitle observableTitle = new((Application.Current.FindResource("AppName") as string)!);
public MainWindow(ILogger<MainWindow> logger)
{
_logger = logger;
DataContext = observableTitle;
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
observableTitle.CurrentFileName = "SomeFile";
}
}
The title is correctly displayed when starting the app: "Untitled - SharpNote" (AppName is a static resource with the value "SharpNote"). However, when clicking the button, the title does not update (should be "SomeFile - SharpNote").
CodePudding user response:
You need to inform the Binding mechanism that the calculated property Title
may have changed and needs to be re-evaluated. Add
PropertyChanged?.Invoke(this, new(nameof(Title)));
to the setter of CurrentFileName and IsUnsaved.
BTW: PropertyChanged?.Invoke(this, new(nameof(_isUnsaved)));
in your code is wrong; it needs to be PropertyChanged?.Invoke(this, new(nameof(IsUnsaved)));