WPF - 如何将事件从Collection类冒泡到主窗口

时间:2009-08-04 15:36:42

标签: wpf polling objectdataprovider

我正在使用ObjectDataProvider来调用IObservableCollection的类:

<ObjectDataProvider x:Key="WaitingPatientDS" 
      ObjectType="{x:Type local:clsPatients}">
      <ObjectDataProvider.ConstructorParameters>
          <sys:Boolean>True</sys:Boolean>
      </ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>

clsPatient抓取数据并填充集合。它还使用计时器以间隔轮询重新查询数据库。

问题:如何在clsPatient中为StartPoll和EndPoll创建一个事件,更重要的是,如何将这些事件冒充到我的WPF窗口的代码隐藏?

1 个答案:

答案 0 :(得分:0)

我不清楚什么是与谁以及如何联系,所以让我告诉你我是如何做到的。

ODP构造clsPatients的一个实例,其中包含一个填充了“data”的“集合”。

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还有一个DispatcherTimer,它定期更新Data属性并触发PropertyChanged

public void DispatcherTimerTick(object sender, EventArgs e)
{
  Data = new BindingList(Repository.GetMyDataLol());
  // standard event firing method here, move along:
  OnPropertyChanged("Data");
}

在用户界面中,我会这样绑定这个集合(这可能是没有错误的,或者可能没有错误):

<ItemsControl 
  ItemsSource="{Binding Data Source={StaticResource WaitingPatientDS}}">
  <ItemsControl.Resources>  
    <DataTemplate>
      <!-- yadda -->

更新数据时如何更新UI:

  1. clsPatient由ObjectDataProvider
  2. 提供给ItemsControl
  3. ItemsControl使用WPF绑定基础结构绑定ODP提供的实例的Data属性。
  4. clsPatient的DispatcherTimer(在UI线程上运行)更新Data并触发PropertyChanged,它通知订阅此事件的所有绑定,该属性具有讽刺意味的变化
  5. 绑定接管并刷新ItemsControl

  6. 要显示指示正在加载的动画,请向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>
    

    当“加载”设置为“可见”时,将显示“图像”(或您要使用的任何其他控件),当“加载”设置为“隐藏”时,它将消失。因此,您可以在加载数据时显示图像。


    如果UI未更新,则该过程可能会阻止UI在UI线程中执行。

    要解决此问题,请运行System.Threading.Timer而不是DispatcherTimer。 STT在除UI之外的后台线程上运行。在timer的回调方法中,使用调度程序更新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");});
    }