何が誰に、どのようにつながっているのかはっきりしないので、どうすればよいかをお話ししましょう。
ODP は、「データ」で満たされた「コレクション」を含む clsPatients のインスタンスを構築します。
public class clsPatients, INotifyPropertyChanged
{
public IBindingList Data {get;private set;}
private DispatcherTimer _timer;
public ClsPatients()
{
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(someInterval);
_timer.Tick += DispatcherTimerTick;
_timer.Start();
}
/* etc etc */
}
clsPatients には、定期的に Data プロパティを更新し、PropertyChanged を起動する DispatcherTimer もあります。
public void DispatcherTimerTick(object sender, EventArgs e)
{
Data = new BindingList(Repository.GetMyDataLol());
// standard event firing method here, move along:
OnPropertyChanged("Data");
}
UI では、このコレクションに対して次のようにバインドします (これにはバグがないか、そうでない可能性があります)。
<ItemsControl
ItemsSource="{Binding Data Source={StaticResource WaitingPatientDS}}">
<ItemsControl.Resources>
<DataTemplate>
<!-- yadda -->
データが更新されたときに UI を更新するためにこれがどのように機能するか:
- clsPatient は ObjectDataProvider によって ItemsControl に提供されます
- ItemsControl は、WPF バインディング インフラストラクチャを使用して、ODP によって提供されるインスタンスの Data プロパティに対してバインドします。
- clsPatient の DispatcherTimer (UI スレッドで動作) は Data を更新し、PropertyChanged を起動します。これにより、皮肉なことに、プロパティが十分に変更されたことを、このイベントにサブスクライブするすべてのバインディングに通知されます。
- バインディングは、ItemsControl を引き継ぎ、更新します。
読み込みが進行中であることを示すアニメーションを表示するには、clsPatient に Loading という別のプロパティを追加します。
public Visibility Loading{get;private set}
タイマー ティック イベントを更新します。
public void DispatcherTimerTick(object sender, EventArgs e)
{
Loading = Visibility.Visible;
OnPropertyChanged("Loading");
Data = new BindingList(Repository.GetMyDataLol());
OnPropertyChanged("Data");
Loading = Visibility.Hidden;
OnPropertyChanged("Loading");
}
次に、UI で、インジケーターの Visibility プロパティを Loading にバインドします。
<Grid DataContext="{Binding Data Source={StaticResource WaitingPatientDS}}">
<ItemsControl
ItemsSource="{Binding Data}">
<ItemsControl.Resources>
<DataTemplate>
<!-- yadda -->
</ItemsControl>
<Image Source="hurf.jpg" Visibility="{Binding Loading}"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
Loading が Visible に設定されている場合は Image (または使用するその他のコントロール) が表示され、Hidden に設定されている場合は消えます。そのため、データを読み込んでいるときに画像を表示できます。
UI が更新されていない場合は、プロセスが UI スレッドでの実行中に UI をブロックしている可能性があります。
これを修正するには、DispatcherTimer の代わりに System.Threading.Timer を実行します。STT は、UI 以外のバックグラウンド スレッドで実行されます。タイマーのコールバック メソッドで、ディスパッチャーを使用して UI を更新します (Invoke メソッドにはバグがある可能性があります。Dispatcher.Invoke のドキュメントを確認してください)。
public void UpdateData(Object stateInfo)
{
var disp = Dispatcher.CurrentDispatcher();
Loading = Visibility.Visible;
disp.Invoke(() => { OnPropertyChanged("Loading");});
// optional sleep here
Data = new BindingList(Repository.GetMyDataLol());
disp.Invoke(() => { OnPropertyChanged("Data");});
Loading = Visibility.Hidden;
disp.Invoke(() => { OnPropertyChanged("Loading");});
}