WPF OneWay binding works only once - c#

I have a View that have two comboboxes. One is where user selects routing pipe type name, and the other where there should be a list of available diameters for the chosen pipe type.
Whenever user selects the pipe type, the other combobox should update the list of available diameters.
AvailableDiameters and RoutingPipeTypeName properties are static in Context class, that implements INotifyPropertyChanged interface. In xaml I've set the bindings to these properties, in code behind also the DataContext.
The problem is that the list of diameters get's updated only once, when the view is initialized.
When debugging I can see that the properties backing field's values are updated properly when selection on pipe type name is changed, only in the UI the available diameters list is not updated...
Context class:
public class Context : INotifyPropertyChanged
{
public static Context This { get; set; } = new Context();
public static string RoutingPipeTypeName
{
get => _routingPipeTypeName;
set
{
if (_routingPipeTypeName != value)
{
_routingPipeTypeName = value;
This.OnPropertyChanged(nameof(RoutingPipeTypeName));
}
}
}
public static List<double> AvailableDiameters
{
get => _availableDiameters;
set
{
//check if new list's elements are not equal
if (!value.All(_availableDiameters.Contains))
{
_availableDiameters = value;
This.OnPropertyChanged(nameof(AvailableDiameters));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
xaml:
<ComboBox Width="80" SelectedValue="{Binding Path=RoutingPipeTypeName, Mode=OneWayToSource}">
<ComboBoxItem Content="Example pipe type 1"></ComboBoxItem>
<ComboBoxItem Content="Example pipe type 2"></ComboBoxItem>
</ComboBox>
<ComboBox Width="80" SelectedValue="{Binding Path=RoutingDiameter, Mode=OneWayToSource}" ItemsSource="{Binding Path=AvailableDiameters, Mode=OneWay}">
</ComboBox>
code behind:
public Context AppContext => Context.This;
public MyView()
{
InitializeComponent();
Instance = this;
DataContext = AppContext;
}
And the client class that is responsible for updating the list of diameters:
public void InitializeUIContext()
{
Context.This.PropertyChanged += UIContextChanged;
if (Cache.CachedPipeTypes.Count > 0)
Context.RoutingPipeTypeName = Cache.CachedPipeTypes.First().Key;
}
private void UIContextChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Context.RoutingPipeTypeName))
{
Context.AvailableDiameters = Cache.CachedPipeTypes.First().Value.GetAvailableDiameters();
}
}
I expected such set-up would update the diameters combobox each time the selection is changed on the pipe types property.
Instead it updates it only once, when the view is initialized... Why?

Do not use static properties for binding to an object (which you have correctly passed to the DataContext of your view).
Declare the properties without the static modifier and replace This.OnPropertyChanged by OnPropertyChanged:
public string RoutingPipeTypeName
{
get => _routingPipeTypeName;
set
{
if (_routingPipeTypeName != value)
{
_routingPipeTypeName = value;
OnPropertyChanged(nameof(RoutingPipeTypeName));
}
}
}
You should also remove the static This from your Context class and simply write
public Context AppContext { get; } = new Context();

Related

WPF - DataGrid doesn't show list

My goal is to output a list in a datagrid, but this doesn't work and the datagrid is empty.
I tried to display the list in an other way and it did (but I can't remember what it was) and it worked, except for it not being in a datagrid but just data. I have changed up some things, but back then it reached the end and got displayed.
ViewModel in Mainwindow:
public class ViewModel
{
public List<ssearch> Items { get; set; }
private static ViewModel _instance = new ViewModel();
public static ViewModel Instance { get { return _instance; } }
}
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
//For simplicity, let's say this window opens right away
var Mdata = new MDataWindow { DataContext = DataContext };
Mdata.Show();
}
Other Window for data display:
string searchParam = "status = 1";
public MDataWindow()
{
InitializeComponent();
}
private void AButton_Click(object sender, RoutedEventArgs e)
{
MainWindow.ViewModel.Instance.Items = Search(searchParam);
}
public List<ssearch> Search(string where)
{
{
//Lots of stuff going on here
}
return returnList;
}
And in WPF:
<Window x:Class="WPFClient.MDataWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFClient"
mc:Ignorable="d"
Title="MDataWindow" Height="Auto" Width="Auto">
<StackPanel>
<Button x:Name="AButton" Click="AButton_Click" Content="Load" />
<DataGrid ItemsSource="{Binding Items}" />
</StackPanel>
</Window>
I have no clue where the error is and tried to strip the code down as much as possible without killing error sources. The Datagrid just stays empty when I press the "Load" button.
EDIT:
I tried to convert the list into an observableColletion before passing it to the ViewModel, but this didn't work. I am working with a library, which I am not sure how to use observableCollection with, so I converted it instead of using it right away:
VM:
public ObservableCollection<Product> Items { get; set; }
Data Window:
List<Product> pp = Search_Products(searchParam);
var oc = new ObservableCollection<Product>(pp);
MainWindow.ViewModel.Instance.Items = oc;
First, change your List<Product> to an ObservableCollection<Product> as this will help to display the Items of the list on Add/Remove immediately.
This is because ObservableCollection implements the INotifyCollectionChanged interface to notify your target(DataGrid) to which it is bound, to update its UI.
Second, your binding can never work as expected due to changed reference of your collection.
private void AButton_Click(object sender, RoutedEventArgs e)
{
// You are changing your Items' reference completely here, the XAML binding
// in your View is still bound to the old reference, that is why you're seeing nothing.
//MainWindow.ViewModel.Instance.Items = Search(searchParam);
var searchResults = Search(searchParam);
foreach(var searchResult in searchResults)
{
MainWindow.ViewModel.Instance.Items.Add(searchResult);
}
}
Make sure you have changed the List to ObservableCollection upon running the Add loop, else you will get an exception saying the item collection state is inconsistent.
The ViewModel class should implement the INotifyPropertyChanged interface and raise its PropertyChanged event whenever Items is set to a new collection:
public class ViewModel : INotifyPropertyChanged
{
private List<ssearch> _items;
public List<ssearch> Items
{
get { return _items; }
set { _items = value; OnPropertyChanged(); }
}
private static ViewModel _instance = new ViewModel();
public static ViewModel Instance { get { return _instance; } }
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
This is required to notify the view regardless of the type of Items.
If you change the type of Items to ObservableCollection<T>, you should initialize the collection in the view model once:
public class ViewModel
{
public ObservableCollection<ssearch> Items { get; } = new ObservableCollection<ssearch>();
private static ViewModel _instance = new ViewModel();
public static ViewModel Instance { get { return _instance; } }
}
...and then add items to this collection instead of setting the property to a new one:
private void AButton_Click(object sender, RoutedEventArgs e)
{
MainWindow.ViewModel.Instance.Items.Clear();
var search = Search(searchParam);
if (search != null)
foreach (var x in search)
MainWindow.ViewModel.Instance.Items.Add(x);
}

WPF combobox does not update when values change

I have WPF application with Combobox and Button. After I enter value into textbox and press button, the value from textbox should appear in updated list of combobox. I am trying to achieve this with MVVM and binding to combobox. Here is part of code from ViewModel.
public class ViewModel:INotifyPropertyChanged
{
DomainLogic dl = new DomainLogic();
public event PropertyChangedEventHandler PropertyChanged;
private ObservableCollection<string> expenseCategories = new ObservableCollection<string>();
public ObservableCollection<string> ExpenseCategories
{
get
{
return expenseCategories;
}
set
{
expenseCategories = value;
OnPropertyChanged("ExpenseCategories");
}
}
public ViewModel()
{
expenseCategories = new ObservableCollection<string>(dl.GetExpenseCategories());
}
private void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
Also I am using EF to access DB and DomainLogic class has a method to list all Expense Categories.
Here is code-behind from window:
DomainLogic dl = new DomainLogic();
public Window1()
{
InitializeComponent();
DataContext = new ViewModel();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrWhiteSpace(textBox.Text))
{
dl.CreateNewExpenseCategory(textBox.Text);
}
else
{
MessageBox.Show("Enter category!");
}
}
Here is also XAML:
<ComboBox x:Name="ExpCategory" HorizontalAlignment="Left" Margin="72,50,0,0" VerticalAlignment="Top" Width="130" ItemsSource="{Binding ExpenseCategories, UpdateSourceTrigger=PropertyChanged}" />
When I add the new category the combobox isn't updated. I'm new to the whole MVVM pattern and I think I'm missing something here.
//EDIT
public void CreateNewExpenseCategory(string name)
{
using (var context = new ExpenseEntities())
{
ExpenseCategory category = new ExpenseCategory() { CategoryName = name};
context.ExpenseCategory.Add(category);
context.SaveChanges();
}
}
The problem is that CollectionChanged event doesn't fire.
You are adding a new element inside your DataContext, but you aren't updating your local view of data.
Once you update the DataContext you should refresh your ObservableCollection or use Local.
Here how you could use Local:
public ViewModel()
{
expenseCategories = dl.GetExpenseCategories().Local;
}
So you can directly do:
expenseCategories.Add(new ExpenseCategory() {textBox.Text});
dl.GetContext().SaveChanges();
Or you have to update the ObservableCollection:
dl.CreateNewExpenseCategory(textBox.Text);
// Update your ViewModel ObservableCollection.
However i think that you should use a Command and not an Event so you can update the ObservableCollection directly inside the ViewModel.
Example:
using Prism.Commands;
//Other usings
public class ViewModel : INotifyPropertyChanged
{
// Your class methods and properties
public DelegateCommand<string> AddNewExpenseCategory
{
get
{
return new DelegateCommand<string>(Execute_AddNewExpenseCategory);
}
}
public void Execute_AddNewExpenseCategory(string param)
{
expenseCategories.Add(new ExpenseCategory() { param });
dl.GetContext().SaveChanges();
}

WPF Binding: disable TextBoxes + Validation and DataContext Issue

My simple program has two windows:
from the first one I set a Boolean value, which then...
I'll use in the second window to disable a number of TextBoxes depending on the aforementioned value itself.
Said TextBoxes are also characterized by a validation binding. At now my validation task is flawlessly working, but I'm not able to make the binding to the IsEnabled TextBox property work.
This is the snippet of my XAML containing one of the TextBoxes (for now the only one I've bound):
<TextBox x:Name="tbSlave1" Validation.Error="ValidationError" IsEnabled="{Binding TextBoxEnabled}" Text="{Binding UpdateSourceTrigger=PropertyChanged, Path=SlavePoint1Name, ValidatesOnDataErrors=true, NotifyOnValidationError=true}"/>
While this is my second window class:
public partial class GeneratorWindow : Window, INotifyPropertyChanged
{
private readonly Validator validator = new Validator();
private int noOfErrorsOnScreen;
public GeneratorWindow()
{
this.InitializeComponent();
this.grid.DataContext = this.validator;
}
public int NumberOfPoints { private get; set; }
public int MainPDC { private get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
private Boolean IsEnabled;
public Boolean TextBoxEnabled
{
get { return IsEnabled; }
set
{
IsEnabled = value;
NotifyPropertyChanged("TextBoxEnabled");
}
}
private void ValidationError(object sender, ValidationErrorEventArgs eventArgs)
{
if (eventArgs.Action == ValidationErrorEventAction.Added)
{
this.noOfErrorsOnScreen++;
}
else
{
this.noOfErrorsOnScreen--;
}
}
private void ValidationCanBeExecuted(object sender, CanExecuteRoutedEventArgs eventArgs)
{
eventArgs.CanExecute = this.noOfErrorsOnScreen == 0;
eventArgs.Handled = true;
}
private void ValidationExecuted(object sender, ExecutedRoutedEventArgs eventArgs)
{
// If the validation was successful, let's generate the files.
this.Close();
eventArgs.Handled = true;
}
}
For now, what I'm getting back is that my window is disabled (can't select any TextBox) and, obviously, this:
System.Windows.Data Error: 40 : BindingExpression path error: 'TextBoxEnabled' property not found on 'object' ''Validator' (HashCode=14499481)'. BindingExpression:Path=TextBoxEnabled; DataItem='Validator' (HashCode=14499481); target element is 'TextBox' (Name='tbSlave1'); target property is 'IsEnabled' (type 'Boolean')
From what I can understand, the culprit is the way I'm managing the DataContext in my class constructor. I probably need to add something to the validator line or totally change it, but I can't understand how.
I think you should be fine if you set the DataContext to the GeneratorWindow and updated you bindings accordingly. For that to work you need to change Validator to a public property.
Changed Validator definition:
public Validator Validator { get; } = new Validator();
DataContext:
this.grid.DataContext = this;
Updated Binding:
<TextBox x:Name="tbSlave1"
Validation.Error="ValidationError"
IsEnabled="{Binding TextBoxEnabled}"
Text="{Binding UpdateSourceTrigger=PropertyChanged,
Path=Validator.SlavePoint1Name,
ValidatesOnDataErrors=true,
NotifyOnValidationError=true}"/>

Update ComboBox Items when TextBox value changed

Hi I am beginner using C# trying to produce a WPF(MVVM).
I have currently a TextBox & a ComboBox on a Window Form.
At the moment, I would like to arrange such that when user input an Access DB file path into the TextBox, the ComboBox will be automatically updated such that its available Items is the Tables Name in the MDB file. When user changed the MDB file path to another, ComboBox Items will be refreshed as well.
I have already prepared below Properties in the GUI's ViewModel.
...
public string MdbDir { get{;} set {; RaisePropertyChanged("MdbDir");} }
public List<string> MdbTblList { get{;} set{...; RaisePropertyChanged("MdbTblList");}}
...
I have already prepared below method in the Model.
...
public List<string> ReturnMdbTblList(string mdbDir)
{
List<string> mdbTblList = new List<string>();
oCat = new ADOX.Catalog();
oCat.ActiveConnection = oConn;
foreach (ADOX.Table oTable in oCat.Tables)
{
mdbTblList.Add(oTable.Name);
}
return mdbTblList;
}
...
I have already prepared below in View.xaml
...
<TextBox Grid.Column="1" Grid.ColumnSpan="2" Text="{Binding MdbDir}" />
<ComboBox Grid.Column="1" Grid.Row="3" SelectedItem="{Binding Path=SelectedMdbTbl,Mode=TwoWay}" ItemsSource="{Binding MdbTblList}"/>
...
All I don't know is how to link the Model Method to ViewModel, and to make the ComboBox aware of MdbDir changed.
Any idea on what else to add the coding and at the same time minimize the amendment on the current piece of coding?
Thanks very much in advance :)
You can do that in two ways.
When ever you type the path in textBox and press tab, the Set part of the property MdbDir will be called. So you can call method like below. And in that method method you can fetch the details from the Model and update it to the UI.
public string MdbDir
{
get
{
;
} set
{
;
RaisePropertyChanged("MdbDir");
UpDateTheList()
}
}
Or you can have button on the UI and click of that can do the same thing. to Bind commands to buttons you can refer the below links
http://theprofessionalspoint.blogspot.in/2013/04/icommand-interface-and-relaycommand.html
http://www.codeproject.com/Articles/126249/MVVM-Pattern-in-WPF-A-Simple-Tutorial-for-Absolute
One more observation, if your new creating list every time then List is fine, but if your adding or removing something with already existing list then it'll not work for you, you have to use observablecollection instead of list
It is acceptable for your ViewModel to maintain a reference to your Model as the ViewModel can be thought of as a wrapper for your Model.
You could put a call to your Model method ReturnMdbTblList such as:
public string MdbDir
{
get
{
return this.mdbDir;
}
set
{
this.mdbDir = value;
RaisePropertyChanged("MdbDir");
this.MdbTblList = this.model.ReturnMdbTblList(value);
}
}
This is straight forward to implement and effective. My personal preference is not put anything inside the get and set methods of properties that do not directly affect the field it is accessing or notifying others it has changed. That is just my preference though, others may be happy to do so and I am not saying it is wrong.
I would use a DelegateCommand on the button to make the call to your ReturnMdbTdlList:
Model, ViewMode & DelegateCommand
public class MyViewModel : INotifyPropertyChanged
{
private readonly MyModel model;
private string mdbDir;
public string MdbDir
{
get
{
return this.mdbDir;
}
set
{
this.mdbDir = value;
RaisePropertyChanged("MdbDir");
}
}
private List<string> mdbTblList;
public List<string> MdbTblList
{
get
{
return this.mdbTblList;
}
set
{
this.mdbTblList = value;
RaisePropertyChanged("MdbTblList");
}
}
private DelegateCommand updateMdbTblListCommand;
public ICommand UpdateMdbTblListCommand
{
get
{
return this.updateMdbTblListCommand ??
(this.updateMdbTblListCommand = new DelegateCommand(this.UpdateMdbTblList));
}
}
public MyViewModel()
{
// This would idealy be injected via the constructor
this.model = new MyModel();
}
private void UpdateMdbTblList(object obj)
{
var param = obj as string;
this.MdbTblList = this.model.ReturnMdbTblList(param);
}
#region [ INotifyPropertyChanged ]
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
public class MyModel
{
public List<string> ReturnMdbTblList(string mdbDir)
{
// Do soemthing
return new List<string>();
}
}
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
public DelegateCommand(Action<object> execute,
Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return this._canExecute == null || this._canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
XAML
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<TextBox Height="23" Margin="10" Width="200" Text="{Binding MdbDir}" />
<Button Content="Click Me" Width="100" Height="25" Margin="10" Command="{Binding Path=UpdateMdbTblListCommand}" CommandParameter="{Binding Path=MdbDir}" />
</StackPanel>
We bind the Command property of the Button to our UpdateMdbTblCommand in the MyViewModel, we also bind the CommandParameter property of the Button to the MdbDir property of MyViewModel. When the Button is pressed the UpdateMdbTblCommand is executed which in turn calls the UpdateMdbTbl passing along the value of MdbDir as an argument and subsequently updating the MdbTblList property of MyViewModel.
As I said the DelegateCommand would be my preferred method, however, it may be overkill when taking into consideration what you have to write to achieve what can be done in the former example.

Why wont UI update on RaisePropertyChanged?

I have a static IList which acts as a repository in a static class:
//static class Settings
public static IList RecentSearchedRepo = new ObservableCollection<object>();
and an IList located in another class which I bind my UI grid to :
//component class
private IList recentsearch = new ObservableCollection<object>();
public IList RecentSearch
{
get
{
return recentsearch;
}
set
{
recentsearch = value;
RaisePropertyChanged("RecentSearch");
}
}
I add objects to RecentSearchedRepo :
RecentSearchedRepo.add(searchitem)
then set RecentSearch to the static list
RecentSearch = Settings.RecentSearchedRepo;
XAML snippet:
<GridLayout:RecentSearchGrid x:Name="recentSearchGrid" ItemsSource="{Binding RecentSearch}" />
snippet from RecentSearchGrid class which extends UserControl:
public IList ItemsSource
{
get
{
return GetValue(ItemsSourceProperty) as IList;
}
set
{
SetValue(ItemsSourceProperty, value);
}
}
private static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IList), typeof(RecentSearchGrid), new PropertyMetadata(null, OnItemsSourcePropertyChanged));
private static void OnItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RecentSearchGrid source = d as RecentSearchGrid;
if (source != null)
{
source.setListforgrid(source.ItemsSource);
}
}
The problem is when I add the first item to RecentSearchedRepo the UI is updated , but on every subsequent add the UI does not update.
Instead of:
RecentSearch = Settings.RecentSearchedRepo;
Try doing:
RecentSearch.Clear();
var freshData = Settings.RecentSearchedRepo;
if (freshData != null)
foreach (var item in freshData)
RecentSearch.Add(item);
You were killing the binding by reassigning the reference.
EDIT: After yours
You're doing it backwards: that OnItemsSourcePropertyChanged shouldn't be setting the source, it shouldn't be there at all actually.
You must bind, in RecentSearchGrid.xaml, to the ItemsSource dependency property declared in RecentSearchGrid.xaml.cs
I don't think that there's enough information here to answer your question. The following simple application mirrors the scenario that I see described in the question and it works as expected:
// MySettings.cs
public static class MySettings
{
public static IList RecentSearchedRepo = new ObservableCollection<object>();
}
// MyVm.cs
public class MyVm : INotifyPropertyChanged
{
private IList recentSearch = new ObservableCollection<object>();
public event PropertyChangedEventHandler PropertyChanged;
public MyVm()
{
this.RecentSearch = MySettings.RecentSearchedRepo;
}
public IList RecentSearch
{
get { return recentSearch; }
set
{
recentSearch = value;
this.RaisePropertyChanged("RecentSearch");
}
}
private void RaisePropertyChanged(string p)
{
if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(p));
}
}
// MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
// Initialization as described in the question
MySettings.RecentSearchedRepo.Add("SearchItem1");
MySettings.RecentSearchedRepo.Add("SearchItem2");
this.DataContext = new MyVm();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
// Add a new item later
MySettings.RecentSearchedRepo.Add("NewlyAddedSearchItem");
}
}
// MainWindow.xaml
<Window x:Class="ScratchWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<Button DockPanel.Dock="Bottom" Content="Add new Search Item" Click="Button_Click_1" />
<ListBox ItemsSource="{Binding RecentSearch}" />
</DockPanel>
</Window>
I'm going to try putting on my psychic hat and ask if, perhaps, you are adding additional items to the wrong collection. Does the collection get recreated and placed at the binding after a single item is added, but later items are added to the original collection instead of the new one?
Given that you stated RecentSearchGrid is a UserControl, we can also infer that the implementation of ItemsSource may be a custom one rather than the standard one that would be inherited from an ItemsControl. It's possible that the RecentSearchGrid is breaking the binding incorrectly in there somehow.
I agree with Baboon. What is the purpose of OnItemsSourcePropertyChanged? In a typical implementation, I wouldn't expect that to be there.
The problem may be as follow:
OnItemsSourcePropertyChanged will not get called, if the instance does not change.
From WPF point of view, when you RaisePropertyChangeEvent, but the instance of the bound collection does not change, PropertyChange handler will not be called at all.
Is Settings.RecentSearchedRepo the same instance through the lifetime of the app?

Categories