Reputation: 4885
Edit: Changed List to ObservableCollection, got the same issue
I have got a global object which holds values needed for the duration of the application runtime. For some reason the ListView isn't being populated, not too sure if I have coded something wrong, or if the ListView simply isn't being updated for some reason.
Here is the class:
App.xaml.cs
/// <summary>
/// Global values for use during application runtime
/// </summary>
public class runtimeObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
private ObservableCollection<string> _hashList;
public ObservableCollection<string> hashList
{
get { return _hashList; }
set
{
if (value = "true")
{
_hashList.Clear();
}
else
{
_hashList.Add(value);
OnPropertyChanged("hashList");
}
}
}
}
I have created a command to populate this List so I can test it's binding. Here is the command:
Commands.cs
/// <summary>
/// Command: Test
/// </summary>
public static RoutedUICommand Test
{
get { return _Test; }
}
public static void Test_Executed(object sender,
ExecutedRoutedEventArgs e)
{
var runtime = (runtimeObject)Application.Current.TryFindResource("runtimeVariables");
runtime.hashList = "ONE";
runtime.hashList = "ONE";
runtime.hashList = "ONE";
runtime.hashList = "ONE";
runtime.hashList = "ONE";
}
public static void Test_CanExecute(object sender,
CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
Here is my ListView with the binding, the way I have binded it works for a text box on another property, I have defined the static resource like this <local:runtimeObject x:Key="runtimeVariables" />
within App.xaml
MainWindow.xaml
<ListView Height="150" Width="400" ItemsSource="{Binding Source={StaticResource runtimeVariables},Path=hashList}"/>
Edit:
why this?
runtime.hashList = new ObservableCollection<string> { "one" }; shouldn't it be: runtime.hashList.Add("one"); ?
That's what I though, however if I change
runtime.hashList = new ObservableCollection<string> { "five" };
to this
runtime.hashList.Add("one");
How then do I handle that in the class property?
else
{
_hashList.Add(value);
OnPropertyChanged("hashList");
}
I get this error:
Argument 1: cannot convert "System.Collections.ObjectModel.ObservableCollection" to "string"
Edit 2: I want to be able to send a string to my class property, so that I can simply either add a new value to my List, or clear it, but it needs to return the List when requested.
But I can't do this can I? As in order to return the ObservableCollection<string>
I need to set it like so:
public ObservableCollection<string> hashList { }
but this doesn't allow me to send just string data, as it can't convert string to System.Collections...
If this makes sense.
Upvotes: 0
Views: 7329
Reputation: 8594
Your problem is here:
var runtime = (runtimeObject)Application.Current.TryFindResource("runtimeVariables");
runtime.hashList = new ObservableCollection<string> { "one" };
runtime.hashList = new ObservableCollection<string> { "two" };
runtime.hashList = new ObservableCollection<string> { "three" };
runtime.hashList = new ObservableCollection<string> { "four" };
runtime.hashList = new ObservableCollection<string> { "five" };
runtime.hashList = new ObservableCollection<string> { "six" };
Each time, you're creating a new list. You want to assign the ObservableCollection
to the runtime.hashList
property once, then add each string to the collection:
var runtime = (runtimeObject)Application.Current.TryFindResource("runtimeVariables");
runtime.hashList.Add( "one" );
runtime.hashList.Add( "two" );
runtime.hashList.Add( "three" );
runtime.hashList.Add( "four" );
runtime.hashList.Add( "five" );
runtime.hashList.Add( "six" );
The ObservableCollection
class implements another interface called INotifyCollectionChanged
which follows a pattern similar to INotifyPropertyChanged
, except that it raises an OnCollectionChanged
event whenever the contents of the collection are changed. WPF listens for changes to the collection on that event and updates the display appropriately.
Upvotes: 1
Reputation: 7029
You don't need INotifyPropertyChanged
in this case to have the ListView
update itself. That event is used when the entire object is replaced, i.e. you replace the collection with an entirely different collection. What you are really interested in doing is updating the ListView
when items are added to or removed from the collection. That is handled with an entirely different event: INotifyCollectionChanged
. If you bind ItemsSource
to a collection that implements that event then the ListView
will automatically update itself when the collection changes. ObservableCollection
implements that event so that is the collection you want to use.
I would replace your runtimeObject
with this:
public class runtimeObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
private readonly ObservableCollection<string> _hashList = new ObservableCollection<string>();
public ObservableCollection<string> hashList
{
get { return _hashList; }
}
}
And then change yourTest-Executed
method to this:
public static void Test_Executed(object sender, ExecutedRoutedEventArgs e)
{
var runtime = (runtimeObject)Application.Current.TryFindResource("runtimeVariables");
runtime.hashList.Add("one");
runtime.hashList.Add("two");
runtime.hashList.Add("three");
runtime.hashList.Add("four");
runtime.hashList.Add("five");
}
Upvotes: 1
Reputation: 4936
The ListView has no idea that there were new values added to your list, because List<T>
doesn't implement the INotifyPropertyChanged
interface.
You have following options:
List<T>
class to ObservableCollection<T>
class.INotifyPropertyChanged
OnPropertyChanged
on your objectEDIT:
why this?
runtime.hashList = new ObservableCollection<string> { "one" };
shouldn't it be:
runtime.hashList.Add("one");
?
Upvotes: 1
Reputation: 21241
Your are raising PropertyChanged
for hashList
, but the hashList
instance has NOT changed, only the CONTENT of hashList
has changed. WPF has optimisations built in that can prevent any updates occuring if the object hasn't actually changed.
If you want WPF to respond to changes to the content of the list, you need to fire CollectionChanged
instead, and the simplest way to do that is to use ObservableCollection
instead of List
.
Upvotes: 2