I have an issue with some of my properties not being updated when I use a Dispatcher
from a separate thread. When I check for values in the array, they're all 0's.
Properties:
private string[] _years;
public string[] Years
{
get { return _years; }
private set
{
if (_years == value)
{
return;
}
_years = value;
OnPropertyChanged("Years");
}
}
private int[] _yearCounts;
public int[] YearCounts
{
get { return _yearCounts; }
private set
{
if (_yearCounts == value)
{
return;
}
_yearCounts = value;
OnPropertyChanged("YearCounts");
}
}
private ObservableCollection<RecordModel> _missingCollection;
public ObservableCollection<RecordModel> MissingCollection
{
get { return _missingCollection; }
private set
{
if (_missingCollection == value)
{
return;
}
_missingCollection = value;
OnPropertyChanged("MissingCollection");
}
}
Constructor:
public MissingReportsViewModel()
{
YearCounts = new int[4];
Years = new string[4];
Initialize();
}
Methods:
private void Initialize()
{
SetYears();
Task task = new Task(() =>
{
MissingCollection = new AccessWorker().GetMissingReports();
});
task.ContinueWith((result) =>
{
SetYearCounts();
});
task.Start();
}
private void SetYears()
{
for (int i = 0; i < 4; i++)
{
Years[i] = DateTime.Now.AddYears(-i).Year.ToString();
}
}
private void SetYearCounts()
{
for (int i = 0; i < 4; i++)
{
int n = i;
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() => YearCounts[n] = MissingCollection.Where(item =>
item.RepNum.Substring(0, 4).Equals(Years[n])).ToList().Count()));
}
}
INotifyPropertyChanged:
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
The problem is that after this is ran, each index of YearsCount
is set at 0
. If I get rid of Task.Run() and Dispatcher
, the program freezes up a bit during the lengthy operation, but everything is displayed properly. So, I'm messing up somewhere and failing to properly update the YearsCount
property.
EDIT (SOLUTION?):
Huge thanks to Garry Vass, who hanged in there through two of my lengthy questions, Jon Skeet (from the first post), and Shoe. I was able to get it up and running without any issues like this:
XAML
Four years:
<TextBlock TextWrapping="Wrap"
Style="{DynamicResource SectionBodyTextStyle}">
<Run Text="{Binding YearlyStats[0].Year}"/>
<Run Text=":"/>
</TextBlock>
<TextBlock TextWrapping="Wrap" Grid.Row="1"
Style="{DynamicResource SectionBodyTextStyle}">
<Run Text="{Binding YearlyStats[1].Year}"/>
<Run Text=":"/>
</TextBlock>
<TextBlock TextWrapping="Wrap" Grid.Row="2"
Style="{DynamicResource SectionBodyTextStyle}">
<Run Text="{Binding YearlyStats[2].Year}"/>
<Run Text=":"/>
</TextBlock>
<TextBlock TextWrapping="Wrap" Grid.Row="3"
Style="{DynamicResource SectionBodyTextStyle}">
<Run Text="{Binding YearlyStats[3].Year}"/>
<Run Text=":"/>
</TextBlock>
Four stats (one per year):
<TextBlock Text="{Binding YearlyStats[0].Count}" Grid.Column="1"
Margin="10,0,0,0"/>
<TextBlock Text="{Binding YearlyStats[1].Count}" Grid.Column="1" Grid.Row="1"
Margin="10,0,0,0"/>
<TextBlock Text="{Binding YearlyStats[2].Count}" Grid.Column="1" Grid.Row="2"
Margin="10,0,0,0"/>
<TextBlock Text="{Binding YearlyStats[3].Count}" Grid.Column="1" Grid.Row="3"
Margin="10,0,0,0"/>
C# Code
Data Object:
public class MissingReportInfoModel : INotifyPropertyChanged
{
private string _year;
public string Year
{
get { return _year; }
set
{
if (_year == value)
{
return;
}
_year = value;
OnPropertyChanged("Year");
}
}
private int _count;
public int Count
{
get { return _count; }
set
{
if (_count == value)
{
return;
}
_count = value;
OnPropertyChanged("Count");
}
}
public MissingReportInfoModel()
{
Year = "Not Set";
Count = 0;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
ViewModel Properties:
private ObservableCollection<MissingReportInfoModel> _yearlyStats;
public ObservableCollection<MissingReportInfoModel> YearlyStats
{
get { return _yearlyStats; }
private set
{
if (_yearlyStats == value)
{
return;
}
_yearlyStats = value;
OnPropertyChanged("YearlyStats");
}
}
private ObservableCollection<RecordModel> _missingCollection;
public ObservableCollection<RecordModel> MissingCollection
{
get { return _missingCollection; }
private set
{
if (_missingCollection == value)
{
return;
}
_missingCollection = value;
OnPropertyChanged("MissingCollection");
}
}
ViewModel Constructor:
public MissingReportsViewModel()
{
YearlyStats = new ObservableCollection<MissingReportInfoModel>();
Initialize();
}
ViewModel Methods:
private void Initialize()
{
SetYears();
Task task = new Task(() =>
{
MissingCollection = new AccessWorker().GetMissingReports();
});
task.ContinueWith((result) =>
{
SetCounts();
});
task.Start();
}
private void SetYears()
{
for (int i = 0; i < 4; i++)
{
var info = new MissingReportInfoModel();
info.Year = DateTime.Now.AddYears(-i).Year.ToString();
YearlyStats.Add(info);
}
}
private void SetCounts()
{
for (int i = 0; i < 4; i++)
{
int n = i;
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() =>
{
YearlyStats[n].Count = MissingCollection.Where(item =>
item.RepNum.Substring(0, 4).Equals(YearlyStats[n].Year)).ToList().Count();
}));
}
}