I am using the charting stuff of the WPF toolkit.
After creating a chart I like to have a snaphshot of that chart, without visualizing that chart. My problem is that I don't know when the rendering process is done, so I can create a snapshot.
I tried listening to the "LayoutUpdated" event, but the chart is being updated very often.
Can anyone tell me how to find out if the chart is completely rendered?
You can use the Dispatcher in your code behind:
this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
{
// code in here should be executed after chart has been rendered.
}
));
The Loaded event sounds like what you need.
MyChart.Loaded += (sender, e) =>
{
// chart has been loaded but not yet rendered
}
where "MyChart" is a the name you've given the chart in your XAML.
I'm not sure how well this works with frequent updates, but this link seems to indicate http://blogs.msdn.com/b/mikehillberg/archive/2006/09/19/loadedvsinitialized.aspx that this is what you're looking for.
Related
I am using LiveCharts.WinForms.CartesianChart to render a large amount of points:
myChart.Zoom = ZoomingOptions.X;
myChart.Pan = PanningOptions.X;
myChart.Series.Add(new LineSeries
{
Values = chartValuesScores,
Fill = System.Windows.Media.Brushes.Transparent,
PointGeometrySize = 5
});
myChart.AxisX.Add(new Axis
{
Labels = labels
});
What I want to do is to display some kind of a progressbar and stop the time LiveCharts needs to render this points. But it seems that LiveCharts renders the points asynchronously. That means that after running the code above, it continues running other code lines and exits the function.
Thus, my question is: Is there a way to detect that LiveCharts.WinForms.CartesianChart is finished with rendering? I could not find an event or something else.
I found this while checking the docs: https://lvcharts.net/App/examples/v1/wpf/Events
It lists Chart.UpdaterTick as one of the events. That events seems to fire when the graph has finished loading the data and had rendered it on screen, I believe what you were looking for?
I've tested myself and appears to work as I expect.
There is an CartesianChart.Loaded event, which is fired after the chart is rendered.
myChart.Loaded += myChart_Loaded;
private void myChart_Loaded(object sender, RoutedEventArgs e)
{
// chart is rendered
}
The challenge
I'm trying to create a Window that'll draw a card on a page of a PDF document.
The idea is to receive a collection (of the items that should be drawn on the card), then go through them, and for each of the items, load it to a UniformGrid (to give the impression of a actual card), capture an image of the screen and draw it to a page of a PDF document.
So far so good.
What I've tried (and partially succeeded)
Here's what I've tried:
(the following code was added to a Loaded event handler of the window)
PdfDocument document = new PdfDocument();
// This is just an example
int[][] items = new int[10][];
// Fill the matrix
foreach (int[] array in items)
{
Dispatcher.Invoke(() =>
{
// uGrid is an UniformGrid
uGrid.Children.Clear();
foreach (int id in array)
{
Border child = null;
// Create child element and add it to the Uniform Grid
uGrid.Children.Add(child);
}
});
Dispatcher.Invoke(new Action(() =>
{
// Draws an image of 'this' to the PDFDocument 'document'
PdfHelper.DrawPictureOfControlToPdf(document, this);
// DispatcherPriority.ContextIdle here is responsible for executing the DrawPicture method only after the uGrid has been redrawed
}), DispatcherPriority.ContextIdle, null);
}
// This will save the PDF on your documents folder
document.Save(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MyTestPDF.pdf"));
A full (but very short, I promise) working example can be found on my GitHub
Also, the produced PDFs (when debugging and when not - see problem below), can be found here
The problem
The above code works great when on debugging mode.
When debugging: the code runs without errors, the PDF is created with the correct number of pages, and the cards are correctly drawn on it.
When not: the code runs without errors, the PDF is created with the correct number of pages, but the cards are not drawn on it.
I think that what's causing the issue is the DispatcherPriority.ContextIdle on the following piece of code:
Dispatcher.Invoke(new Action(() =>
{
PdfHelper.DrawPictureOfControlToPdf(document, this);
}), DispatcherPriority.ContextIdle, null);
It should indicate that the Action must only be run when the UniformGrid finished redrawing (or after the Dispatcher took care of it, more precisely). But apparently this only works inside debugging mode.
Does someone know how to solve this?
If not, is there any alternative that I'm not thinking of?
#EDIT
I don't think this is important, but I'm using PDFSharp to generate/handle the PDF
Remove all Dispatcher.Invoke in your code (they are not doing anything good here), and then call
this.UpdateLayout();
to force redraw of current control, before calling PdfHelper.DrawPictureOfControlToPdf(document, this);.
To dynamically place some content on a page in a Windows Phone 8 project, we use a popup with a grid to host the content.
When this page contains a LongListSelector control, the Tap interaction to stop scrolling no longer works. Swiping up and down works as expected.
The issue can be reproduced very easily by starting with a new Databound app and adding this piece of code in the page constructor:
private Popup p;
p = new Popup();
Grid grid = new Grid();
grid.Width = Application.Current.Host.Content.ActualWidth;
grid.Height = Application.Current.Host.Content.ActualHeight;
p.Child = grid;
p.IsOpen = true;
Using this code you can make the LongListSelector scrolling but a Tap does no longer work to stop the scrolling.
Has anyone seen this issue and found a solution or might this be a known issue with the LongListSelector?
The invisible Grid that you're putting over the LongListSelector (actually the whole page) is capturing the tap event and because the popup is not part of the visual tree the event doesn't bubble as you're expecting.
The anomaly here is that you can actually interact with the LLS at all.
The real question here isn't why this happens but why you'd do this? Obviously your reproduction is very simple but it's to a point that makes no sense.
What are you ultimately trying to achieve?
There are almost certainly more appropriate alternative ways to achieve your end goal.
Is there something like an "OnPaint" method in Silverlight?
Back when I was writing C++, I found that it was easy to use the OnPaint event to customize the display of a class to the screen?
Is there an equivalent in Silverlight? If I want to do something when a UserControl is displayed on the screen, what method would I override?
I noticed this post:
C# WPF OnPaint method alternative?
but it seems that in Silverlight, thre is no "OnRender" method for a UserControl class.
OnPaint was a workaround... to allow you to customise the appearance of controls. That was because you did not have much control over the default appearance of any controls in WinForms applications.
With Silverlight that all changes. Every control is now effectively skinned, using templates and styles, and there are few limitations on how you can customise them. There are far too many links so I just grabbed a couple for you.
Get yourself a good book on Silverlight and learn the proper way to work with it (not around it). This one is one of my favorites.
If you have specific things you are trying to do, to the appearance of user controls, best to list those instead and find out the best way to do it the Silverlight way. :)
You haven't specified what you're trying to do. If you just want to know when a frame is being rendered, the CompositionTarget.Rendering Event will tell you that. If you actually want to draw on the frame being rendered, you cannot do so.
It is LayoutUpdated.
As in:
...
this.LayoutUpdated += new EventHandler(LayoutUpdated);
}
void LayoutUpdated(object sender, EventArgs e)
{}
how to a print wpf window after it has been totally rendered which event?
i have tried using loaded but some of the elements have not finished rendered yet
thanks
Read this article it shows you that there currently is no official way of getting notified of the end of the rendering but instead shows you a trick that you could use.
I don't haev a proper solution for you, but you can make the following hack in the loaded event:
Dispatcher.BeginInvoke(new Action(delegate {
// here you are pretty shure that all rendering is done
// Put in your code here
}), System.Windows.Threading.DispatcherPriority.ContextIdle, null);
Probably it will also work with DispatcherPriority.Background, check it out.