2013-09-02 1 views
0

Я хочу показать большую коллекцию точек в виде диаграммы (не менее 300 000 точек), используя диаграмму инструментария wpf.Waiting Dialog white wpf toolkit chart загрузить график

У меня есть следующий код XAML

<chartingToolkit:Chart Name="chartHistory"> 
    <chartingToolkit:Chart.Axes> 
     <chartingToolkit:LinearAxis x:Name="horizontalAxis" Orientation="X" Title="Time [s]" ShowGridLines="True"/> 
     <chartingToolkit:LinearAxis x:Name="verticalAxis" Orientation="Y" Title="Value [mm]" ShowGridLines="True"/> 
    </chartingToolkit:Chart.Axes> 
    <chartingToolkit:AreaSeries x:Name="chartSeries" DataPointStyle="{StaticResource chartDataPoint}" 
     IndependentValuePath="TimeInSeconds" 
     DependentValuePath="Value"> 
    </chartingToolkit:AreaSeries> 
</chartingToolkit:Chart> 

И в коде позади:

public class PointData 
{ 
    public double TimeInSeconds { get; set; } 
    public double Value { get; set; } 
} 

private List<PointData> points; 

private void Screen_Loaded(object sender, RoutedEventArgs e) 
{ 
    // this is a large collection of points (minimum 300 000) 
    points = LoadPointsFromFile(); 

    // and it takes a lot of time to read from the file and load in the UI 
    chartSeries.ItemsSource = points; 

    // additional chart display properties (setting min/max on the axes etc.) 
} 

Итак, у меня есть 2 трудоемких операций, которые блокируют мой UI. Я хочу показать диалоговое окно «пожалуйста, загрузите», в то время как длительные операции выполняются, так что пользователь знает, что приложение все еще что-то делает.

Времени потребляющих операции:

  1. чтения точек из файла (эта операция может быть сделана в отдельном потоке, но так как следующая операция (загрузка точек на графике), зависит от него и это операция UI, я не помещал ее в отдельный поток)
  2. Загрузка точек в качестве ItemsSource в диаграмму - это операция пользовательского интерфейса и должна выполняться в потоке пользовательского интерфейса. Но как я могу заставить приложение реагировать, так как у меня нет никакого контроля над тем, как отображаются точки - это логика диаграммы?

Итак, любые идеи? У вас были подобные проблемы? Спасибо, Nadia

ответ

0

Фактически, я сделал это, чтобы создать отдельный поток, который отображает другой «диалог загрузки», который отображается во время загрузки данных. Все еще есть около одной секунды с момента закрытия диалогового окна, пока пользовательский интерфейс не станет полностью отзывчивым, но он все же лучше, чем смотреть на невосприимчивый пользовательский интерфейс в течение 5-10 секунд.

public class PointData 
{ 
    public double TimeInSeconds { get; set; } 
    public double Value { get; set; } 
} 

#region Wait Dialog Thread 
private class MainWindowSize 
{ 
    public double Left; 
    public double Top; 
    public double Width; 
    public double Height; 
} 

private Thread newWindowThread = null; 

private void ThreadStartingPoint(object obj) 
{ 
    // WaitDialog is a new window from your project - you can place a animation or message inside it 
    WaitDialog tempWindow = new WaitDialog(); 

    // since we don't have an owner for the window, we need 
    // to compute the location of the popup dialog, so that 
    // its centered inside the main window 
    MainWindowSize wndSize = obj as MainWindowSize; 
    if (wndSize != null) 
    { 
     tempWindow.Left = wndSize.Left + wndSize.Width/2 - tempWindow.Width/2; 
     tempWindow.Top = wndSize.Top + wndSize.Height/2 - tempWindow.Height/2; 
    } 

    // it's very important not to set the owner of this dialog 
    // otherwise it won't work in a separate thread 
    tempWindow.Owner = null; 

    // it shouldn't be a modal dialog 
    tempWindow.Show(); 
    tempWindow.Closed += (sender1, e1) => tempWindow.Dispatcher.InvokeShutdown(); 
    System.Windows.Threading.Dispatcher.Run(); 
} 

private void CreateAndStartWaitWindowThread() 
{ 
    // create a thread only if you don't have an active one 
    if (newWindowThread == null) 
    { 
     // use ParameterizedThreadStart instead of ThreadStart 
     // in order to send a parameter to the thread start method 
     newWindowThread = new Thread(new ParameterizedThreadStart(ThreadStartingPoint)); 
     newWindowThread.SetApartmentState(ApartmentState.STA); 
     newWindowThread.IsBackground = true; 

     // get the properties of the window, in order to compute the location of the new dialog 
     Window mainWnd = App.CurrentApp.MainWindow;  
     MainWindowSize threadParams = new MainWindowSize { Left = mainWnd.Left, Top = mainWnd.Top, Width = mainWnd.ActualWidth, Height = mainWnd.ActualHeight }; 

     // start thread with parameters 
     newWindowThread.Start(threadParams); 
    } 
} 

private void AbortAndDeleteWaitWindowThread() 
{ 
    // abort a thread only if you have an active one 
    if (newWindowThread != null) 
    { 
     newWindowThread.Abort(); 
     newWindowThread = null; 
    } 
} 
#endregion 

private List<PointData> points; 

private void Screen_Loaded(object sender, RoutedEventArgs e) 
{ 
    try 
    { 
     // call this before long operation 
     this.Cursor = Cursors.Wait; 
     CreateAndStartWaitWindowThread(); 

     // this is a large collection of points (minimum 300 000) 
     points = LoadPointsFromFile(); 

     // and it takes a lot of time to read from the file and load in the UI 
     chartSeries.ItemsSource = points; 

     // additional chart display properties (setting min/max on the axes etc.) 
    } 
    catch(Exception ex) 
    { 
     // do something with the exception 
    } 
    finally 
    { 
     // call this after long operation - and make sure it's getting called 
     // so put it in the finally block - to call it even if an exception is raised 
     this.Cursor = Cursors.Arrow; 
     AbortAndDeleteWaitWindowThread(); 
    } 
} 

Источник: http://www.c-sharpcorner.com/uploadfile/suchit_84/creating-wpf-windows-on-dedicated-threads/