WPF combination does not update when collection changes

I am new to WPF.

I am trying to associate string collection with a list.

public ObservableCollection<string> ListString {get; set;} 

Binding and datacontext are set as follows

 <Window x:Class="Assignment2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:validators="clr-namespace:Assignment2" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}, Path=.}"> <Grid> <ComboBox Height="23" HorizontalAlignment="Left" Margin="109,103,0,0" Name="StringComboBox" VerticalAlignment="Top" Width="120" SelectionChanged="StringComboBox_SelectionChanged"> <ComboBox.ItemsSource> <Binding Path="ListString" BindsDirectlyToSource="True" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"></Binding> </ComboBox.ItemsSource> </ComboBox> 

I found out that this is happening because the collection is being updated. If i write

 public MainWindow() { InputString = ""; ListString = new ObservableCollection<string>(); ListString.Add("AAA"); ListString.Add("BBB"); ListString.Add("CCC"); InitializeComponent(); } 

It works, but if I move InitializeComponent() above in the first line, as shown below, it does not work.

  public MainWindow() { InitializeComponent(); InputString = ""; ListString = new ObservableCollection<string>(); ListString.Add("AAA"); ListString.Add("BBB"); ListString.Add("CCC"); } 

What should I do?

+6
source share
4 answers

Solved a problem. Done by INotifyPropertyChanged as follows

 public partial class MainWindow : Window, INotifyPropertyChanged 

changed accessors as follows

  private ObservableCollection<string> listString; public ObservableCollection<string> ListString { get { return listString; } set { listString = value; NotifyPropertyChanged("ListString"); // method implemented below } } 

and added the following event and method to raise the event

 public event PropertyChangedEventHandler PropertyChanged; public void NotifyPropertyChanged(string name) { if (PropertyChanged != null) { PropertyChanged(this,new PropertyChangedEventArgs(name)); } } 

and it works B)

+9
source

what happens if you change your code to

 <Window x:Class="Assignment2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:validators="clr-namespace:Assignment2" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <ComboBox Height="23" HorizontalAlignment="Left" Margin="109,103,0,0" Name="StringComboBox" VerticalAlignment="Top" Width="120" SelectionChanged="StringComboBox_SelectionChanged" ItemsSource="{Binding ListString, Mode=OneWay}"/> 

CS

  public MainWindow() { InitializeComponent(); InputString = ""; ListString = new ObservableCollection<string>(); ListString.Add("AAA"); ListString.Add("BBB"); ListString.Add("CCC"); this.DataContext=this; } 

btw: setting ItemsSource with mode = twoway doesn't make any sense to me. your combobox will never β€œcreate a new data source” for your view model.

EDIT: I think your first solution works due to setting DataContext in xaml. I assume that DataContext = "{Binding RelativeSource = {RelativeSource Self}, Path =.}" Is executed when InitializeComponent () is called; and because your ListString property is just an auto-processor and does not implement INotifyPropertyChanged - your mainwindowview does not receive notification that your ctor is creating a new ListString property.

  public ObservableCollection<string> ListString {get{return _list;}; set{_list=value; OnPropertyChanged("ListString");}} 

should work with both of your approaches, but you must implement INotifyPropertyChanged for your MainWindow class.

0
source

You can either set the item source for combobox to the code behind, or set the datacontext again after populating the list, or you can go with inotifychanged to enhance the property change.

 public MainWindow() { InitializeComponent(); InputString = ""; ListString = new ObservableCollection<string>(); ListString.Add("AAA"); ListString.Add("BBB"); ListString.Add("CCC"); StringComboBox.ItemsSource = ListString; } 
0
source

It seems the problem was the "newbie" ListString . To do this property (selected answer) is one way. Alternatively, by embedding the view or putting it in front of the InitializeComponent , I believe that everything is in order.

If you expect new events to occur frequently, it may be useful to encapsulate the ObservableCollection in the manager class. I found this question after troubleshooting my problems with this setup. I got it working by doing INotifyCollectionChanged and forwarding the event this way

 /// <summary> /// Maintains an observable (ie good for binding) collection of resources that can be indexed by name or alias /// </summary> /// <typeparam name="RT">Resource Type: the type of resource associated with this collection</typeparam> public class ResourceCollection<RT> : IEnumerable, INotifyCollectionChanged where RT : class, IResource, new() { public event NotifyCollectionChangedEventHandler CollectionChanged { add { Ports.CollectionChanged += value; } remove { Ports.CollectionChanged -= value; } } public IEnumerator GetEnumerator() { return Ports.GetEnumerator(); } private ObservableCollection<RT> Ports { get; set; } private Dictionary<string, RT> ByAlias { get; set; } private Dictionary<string, RT> ByName { get; set; } } 
0
source

Source: https://habr.com/ru/post/956643/


All Articles