I have a question about zooming and scrolling. My scroll function doesn't work perfectly, but close enough. Instead of the Maximum value I want to change the ActualMaximum, but that one was protected.
plotBSITotalA.Model.Axes[0].Maximum = hScrollBarA.Value +
(plotBSITotalA.Model.Axes[0].ActualMaximum - plotBSITotalA.Model.Axes[0].ActualMinimum);
plotBSITotalA.Model.Axes[0].Minimum = hScrollBarA.Value;
Ok, here comes the real problem: When I have zoomed in or out, the scroll function won't work anymore in that specific plot Area, where it have been zoomed. Other plotArea's that weren't zoomed, will work perfectly.
Does somebody know, how I can scroll when I zoomed in??
May be, It can be done by connecting two enevts with two methods:
1. event emitted when scrollbar changed with method of changing axes range
2. event emitted when axes range changed with method of changing the scrollbar position
Quite a few views, so maybe still a problem.
As I understand it, your saying the auto scroll stops when you have zoomed back out and subsequently add new values to the series?
Can't find a formal solution, but this works for me
add this to your axis:
xAxis.AxisChanged += OnXAxisChange;
add the method
bool doAxisReset = false;
private void OnXAxisChange(object sender, AxisChangedEventArgs e)
{
//if zoomed fully out, then enable auto scroll
//
if ((e.DeltaMaximum == 0) && (e.DeltaMinimum == 0))
{
doAxisReset = true;
}
}
In the rendering code (ie when you get a new element that triggers autoscrolling) and before InvalidatePlot
if (doAxisReset)
{
xAxis.Reset();
doAxisReset = false;
}
Related
I have some string labels that are associated with a number each.
I've created a Chart element with one ChartArea and one Series which is using the SeriesChartType.Bar type to show my labels on the x-axis (which, confusingly, is the vertical axis when using the Bar type, but anyway...) and show the number as a bar next to it.
Since I have many labels that don't fit on the screen at once, I "enabled" the scrollbar using the Zoom method in my Paint event handler like this:
private void chart1_Paint(object sender, PaintEventArgs e)
{
var scaleView = chart1.ChartAreas.First().AxisX.ScaleView;
var pos = double.IsNaN(scaleView.Position) ? 0.0 : scaleView.Position;
scaleView.Zoom(pos, pos + chart1.Height / 22.0);
}
I don't know if this is the proper way to do that, but it does (almost) what I want:
show the scrollbar if there are too many data points (labels) to fit on the screen
update the visible area properly when the window is resized
There is only one annoying thing: If due to scrolling a long label appears in the visible area or disappears, the area occupied by the labels is adjusted to the longest visible label. I hope these screenshots explain what I mean:
Here one long label is visible (at the bottom):
Here I scrolled up by one unit so that the long label is not visible any more:
This is super annoying during scrolling as everything gets rescaled whenver a long label appears or disappears.
How to fix the area occupied by the labels to always fit the longest label in the series, no matter if it is currently visible or not? I tried IsLabelAutoFit = false for both, x- and y-axis, but that doesn't help.
Ok, I've got it. I used
chartArea.InnerPlotPosition.Auto = false;
InnerPlotPosition.X = 33.333;
to give one third of the chart area to the labels and the other two thirds to the bars.
InnerPlotPosition.Auto = false makes this fixed so that it doesn't update while scrolling.
I have a GridView in a windows store project, that contains some big squares, and inside those i have a list of user images, when i tap on of those images a flyout appears on the right showing some information like this.
the problem is that my gridview extends to the edges of the screen and beyond, and when that does i get this situation, i press the user with the red border near the edge of the screen and flyout appears on left.
My flyout placement is set to Right, and im guessing since the element i press is near the edge it follows the Fall back order with according to this is Right > Left > Top > Bottom.
What i would like to know is how to detect this happens, so i can adjust my flyout position, or another viable alternative :)
After searching through properties and Dependency properties on Flyout and FlyoutBase, I haven't found a way to simply get the actual placement of the Flyout (which is unfortunate because I think that can be important, as we see in your case). Perhaps you can try what was proposed here by implementing a method that compares the desired size of the Flyout with the available space.
You can subscribe to FlyOut.Opened event and compare absolute coordinates of the flyout and the element you're showing it at. Here is an example for top/bottom flyout placement (easily extendable to check for left/right as well):
private void FlyOut_Opened(object sender, object e)
{
GeneralTransform flyOutTransform =
flyOut.Content.TransformToVisual(Window.Current.Content);
Point flyOutPosition =
flyOut.TransformPoint(new Point(0, 0));
GeneralTransform showAtElementTransform =
showAtElementTransform.TransformToVisual(Window.Current.Content);
Point showAtElementPosition =
showAtElementPosition.TransformPoint(new Point(0, 0));
if(flyOutPosition.Y < showAtElementPosition.Y)
{
// top
}
else
{
// bottom
}
}
I have a user control which consists of two controls and four buttons, arranged on a Form: the two controls are on the sides and the buttons in the middle in a vertical row.
When using the control in an app, I place it on a form.
Now, when re-sizing the form horizontally, the two controls just move left or right w/o changing their size.
What I need is that the controls stay anchored to the middle of the form and grow to the sides (sorry about the lack of clarity, I prepared screenshots but the site wouldn't let me attach them).
Is there a way to accomplish this without overriding the Resize event?
Use a TableLayoutPanel as base for your user control.
You need 3 columns and one row. The middle column needs to have a fixed size, and the other 2 you set to 50%. Not to worry, .Net is smart enough to calculate the percent they actually take.
Inside the right and left columns you put your controls and set the Dock property of both to fill. In the middle column you put a panel and set it's Dock property to fill as wall, and In that panel you put the buttons in the middle.
Set your table layout panel Dock to fill as well, and when adding the user control to the form use Dock top, bottom or fill as well.
Erratum:
The above code works most of the time, but it fails for certain Move-Resize sequences. The solution is to respond to the Move and Resize events of the parent form (the consumer of the control), not of the control itself.
One more thing: due to the event firing order (Move first followed by Resize, had to move the working code from Resize() to Move(), which seems counterintuitive but it seems the right way nevertheless.
It seems indeed that it cannot be done in the Designer, but here is the solution using overrides.
It works ok, except for some control flickering which I haven't been able to overcome.
public partial class SB : UserControl
{
//variables to remember sizes and locations
Size parentSize = new Size(0,0);
Point parentLocation = new Point (0,0);
......
// we care only for horizontal changes by dragging the left border;
// all others take care of themselves by Designer code
public void SB_Resize(object sender, EventArgs e)
{
if (this.Parent == null)
return;//we are still in the load process
// get former values
int fcsw = this.parentSize.Width;//former width
int fclx = this.parentLocation.X;//former location
Control control = (Control)sender;//this is our custom control
// get present values
int csw = control.Parent.Size.Width;//present width
int clx = control.Parent.Location.X;//present location
// both parent width and parent location have changed: it means we
// dragged the left border or one of the left corners
if (csw != fcsw && clx != fclx)
{
int delta = clx - fclx;
int lw = (int)this.tableLayoutPanel1.ColumnStyles[0].Width;
int nlw = lw - delta;
if (nlw > 0)
{
this.tableLayoutPanel1.ColumnStyles[0].Width -= delta;
}
}
this.parentSize = control.Parent.Size;//always update it
this.parentLocation = control.Parent.Location;
}
//contrary to documentation, the Resize event is not raised by moving
//the form, so we have to override the Move event too, to update the
//saved location
private void SB_Move(object sender, EventArgs e)
{
if (this.Parent == null)
return;//we are still in the load process
this.parentSize = this.Parent.Size;//always update it
this.parentLocation = this.Parent.Location;
}
}
The above code works most of the time, but it fails for certain Move-Resize sequences. The solution is to respond to the Move and Resize events of the parent form (the consumer of the control), not of the control itself.
One more thing: due to the event firing order (Move first followed by Resize, had to move the working code from Resize() to Move(), which seems counterintuitive but it seems the right way nevertheless.
I have just started looking at potentially using the MSChart control for .Net 3.5 for a project that will be starting shortly. One of the requirements of the project is that the users be able to zoom into the charts to see small data points more clearly when necessary.
I have looked at a number of tutorials and the either do not mention zooming, or just give a brief bit of information about how to enable it and seem to assume that using it is so obvious that it requires no explanation.
I created a quick test project, added the control to the form, and then added a few Points to the default Series. I then went into the ChartAreas collection and made sure that in the default ChartArea, the Zoomable property was set to True in the ScaleView property of all of the Axis members.
When I run the application my chart shows all correctly, but I cannot fathom any way to zoom into it. I have tried clicking on it, double clicking, the scroll wheel, ctrl-scroll wheel, ctrl-+, and many other things.
I am obviously missing something. Could someone please tell me what I am doing wrong, how I enable the zooming UI, and how I actually use the zooming UI?
I am on Windows 7, using VS2012.
Thank you.
[edit: fixed idiotic spelling error in title]
Doing something like the following should allow you to Zoom using the Mouse Left Click and Drag:
private void ZoomToggle(bool Enabled)
{
// Enable range selection and zooming end user interface
this.cwSubplot.ChartAreas(0).CursorX.IsUserEnabled = Enabled;
this.cwSubplot.ChartAreas(0).CursorX.IsUserSelectionEnabled = Enabled;
this.cwSubplot.ChartAreas(0).CursorX.Interval = 0;
this.cwSubplot.ChartAreas(0).AxisX.ScaleView.Zoomable = Enabled;
this.cwSubplot.ChartAreas(0).AxisX.ScrollBar.IsPositionedInside = true;
this.cwSubplot.ChartAreas(0).AxisX.ScrollBar.ButtonStyle = System.Windows.Forms.DataVisualization.Charting.ScrollBarButtonStyles.SmallScroll;
this.cwSubplot.ChartAreas(0).AxisX.ScaleView.SmallScrollMinSize = 0;
this.cwSubplot.ChartAreas(0).CursorY.IsUserEnabled = Enabled;
this.cwSubplot.ChartAreas(0).CursorY.IsUserSelectionEnabled = Enabled;
this.cwSubplot.ChartAreas(0).CursorY.Interval = 0;
this.cwSubplot.ChartAreas(0).AxisY.ScaleView.Zoomable = Enabled;
this.cwSubplot.ChartAreas(0).AxisY.ScrollBar.IsPositionedInside = true;
this.cwSubplot.ChartAreas(0).AxisY.ScrollBar.ButtonStyle = System.Windows.Forms.DataVisualization.Charting.ScrollBarButtonStyles.SmallScroll;
this.cwSubplot.ChartAreas(0).AxisY.ScaleView.SmallScrollMinSize = 0;
if (Enabled == false) {
//Remove the cursor lines
this.cwSubplot.ChartAreas(0).CursorX.SetCursorPosition(double.NaN);
this.cwSubplot.ChartAreas(0).CursorY.SetCursorPosition(double.NaN);
}
}
Where this.cwSubplot is the Chart object you want zooming to work on.
Late Edit I tagged this as a C# question as well as C++ because the problem presents itself in both languages, and solution if shown would most likely be in the C# (the majority of the market).
I have been developing an application under .net 2.0 (C++ to be specific, but irrelevant).
This application uses a custom derived datagridview. This datagridview will occasionally have sever artifacting issues regarding the region of the DGV that does not contain cells, as well as the scrollbar. During some resizing actions, a black rectangle will draw in the bottom portion of the datagridview, which will in effect limit the size of the grid. The scrollbar also gets shrunk to fit inside the nonbugged region. It seems to me as the system believes the DGV is the wrong size, and is drawing into the wrong region.
alt text http://img12.imageshack.us/img12/2213/81356991.jpg
There are only two ways I can find to fix the symptoms:
1. Clicking a column to resize will automatically fix the grid
2. Calling the AutoResizeRows() function in the DGV will do the fix (but I believe is something that is called from point 1).
Some of the modifications to the Custom DGV:
1) Configured to handle drag\drop of multiple rows.
2) Point 1 required OnCellPainting to be overridden to draw drag lines. Function can be posted if it seems symptomatic.
3) The problems always happen on a resize (both manual and automatic can cause the problem), but there is no custom code in the resize event.
late edit code for onCellPainting. Other functions overridden in the gridview: OnMouseDown, OnCellMouseDown, OnClick, OnMouseMove, OnDragOver, OnDragDrop, OnDragLeave, OnKeyDown, None of which seem symptomatic
protected: [DebuggerStepThrough()]
virtual System::Void OnCellPainting(DataGridViewCellPaintingEventArgs ^e) override
{
//draws red drag/drop target indicator lines if necessary
if (this->AllowDrop && _DragDropCurrentIndex > -1 && ShowDragLines)
{
System::Drawing::Pen ^p = gcnew Pen(System::Drawing::Color::Navy, 3);
//row drag/drop
if (e->RowIndex == _DragDropCurrentIndex &&
_DragDropCurrentIndex <= this->RowCount)
{
//if this cell is in the same row as the mouse cursor
e->Graphics->DrawLine(
p,
e->CellBounds.Left,
e->CellBounds.Top - 1,
e->CellBounds.Right,
e->CellBounds.Top - 1);
} //end if
if(e->RowIndex == this->Rows->Count - 1 &&
_DragDropCurrentIndex == Int32::MaxValue)
{
e->Graphics->DrawLine(
p,
e->CellBounds.Left,
e->CellBounds.Bottom + 1,
e->CellBounds.Right,
e->CellBounds.Bottom + 1);
}
} //end if
DataGridView::OnCellPainting(e);
} //end OnCellPainting
*More Edits
None of these work to rid the problem, the only thing that fixes it AFTER the problem happens is AutoResizeRows(AllCells)// Only AllCells fixes it. It's very slow and undesirable.
Refresh();
UpdateBounds();
Update();
Invalidate();
PerformLayout();
ResetBackColor();
ResetBindings();
ResetForeColor();
ResetText();
UpdateStyles();
It sounds to me like your control isn't rendering its layout properly.
Did you suspend layout at some point in your code, and then never resumelayout?
Doing so will allow your control to function properly, but not lay out all of its components properly.
Try setting the .ResizeRedraw property of your control to true in the constructor, see if that helps.
From MSDN:
Gets or sets a value indicating whether the control redraws itself when resized.
Try clearing the graphics with the grid's background in OnPaint:
Graphics g = e.Graphics;
g.Clear(this.BackColor);
I had the same problem caused by some resx files not being loaded that were being referenced from the mDataGridView_CellPainting event. The DataGridView became very slow to resize as well.
I solved this by Maximizing the Form in the load event, populating the Datagridview, and then resetting the Form to the start size. After that, all resizing appears to work as expected. VB.Net code but you get the gist:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim StartSize As Size = Me.Size
Me.Width = Integer.MaxValue
Me.Height = Integer.MaxValue
Me.Visible = False
' ... Populate and format the datagridview ...
Me.Size = StartSize
Me.Visible = True
End Sub