If no height is set, a Stack Panel's height is dynamic based on its contents. My question is: if the c# code sets the height, is there a way (in c#) to wipe those values out and return the Stack Panel to sizing dynamically? Something like this...
spnTest.Height = 100; //expands height to 100, even if contents don't fill it
spnTest.HeightIsDynamic = true; //allows the height of spnTest to go back to being dynamic and expand/contract based on its contents
For some reason, setting the height to double.NaN has no effect...
stkTest.Height = 117;
Console.WriteLine($"Height = {stkTest.Height}"); //writes "Height = 117"
stkTest.Height = double.NaN;
Console.WriteLine($"Height = {stkTest.Height}"); //writes "Height = 117"
.ClearValue(HeightProperty) also does not work
A StackPanel initially measures the needed size of the element by using the sizes of the child elements contained within. This initial measurement should be stored in DesiredSize. I would try using the height that is stored there to get the original measurement for the Element. Check out MSDN entry.
MSDN StackPanel
Related
I have an application that have 2 charts as follows:
Is it possible to programatically show the tooltip of the second chart when hovering on the first chart - via chart 1's DataHover event?
EDIT
The info on the second chart is for Relative Strength Index. It is usually presented at the bottom of the chart. For this reason I made it a separate chart.
Although not an answer to my question, here is what I did. A now deleted comment asked why there are two charts. When I did it like that initially, the charts were over each other.
So I simply went back to that, and applied a scaling factor. 20% of the chart are is fine for the RSI, and as RSI is always calculated out of 100, I set the axis max value to 500% as follows:
chartMain.AxisY.Add(new Axis
{
MaxValue = 500,
MinValue = 0,
IsMerged = true,
Position = AxisPosition.RightTop,
ShowLabels = false,
Sections = new SectionsCollection
{
new AxisSection
{
SectionWidth = m_TradeManager.Settings.RSIThreshold,
Fill = new System.Windows.Media.SolidColorBrush
{
Color = System.Windows.Media.Color.FromRgb(254,132,132),
Opacity = .4
}
}
}
});
The end result is this:
I'm using EPPlus and C# and trying to autosize/autofit the height of a row to accommodate the height needed to show all of the contents of a merged cell with text wrapping. However no matter what I try the text always truncates. Since I'm repeating this process with various text sizes on various worksheets, I don't want to hard code the row height (except to enforce a minimum height for the row). If possible I'd like to do this within EPPlus/C#.
With the cells A2:E2 merged and WrapText = true:
Cell with Text Truncated
Here's what it should look like with desired Cell Height
Here's my relevant and short C# code
Int32 intToCol;
intToCol = 5;
eppWorksheet.Cells[2, 1, 2, intToCol].Merge = true;
eppWorksheet.Cells[2, 1].Style.WrapText = true;
//Check if at the minimum height. If not, resize the row
if (eppWorksheet.Row(2).Height < 35.25)
{
eppWorksheet.Row(2).Height = 35.25;
}
I've looked at Autofit rows in EPPlus and it didn't seem to directly answer my question unless I'm reading it wrong.
Here is the solution in a reusable method. Pass in the text value, font used for the cell, summed width of the columns merged, and receive back the row height. Set the row height with the result.
Use of Method
eppWorksheet.Row(2).Height = MeasureTextHeight(cell.Value, cell.Style.Font, [enter the SUM of column widths A-E]);
Reuseable Method
public double MeasureTextHeight(string text, ExcelFont font, double width)
{
if (text.IsNullOrEmpty()) return 0.0;
var bitmap = _bitmap ?? (_bitmap = new Bitmap(1, 1));
var graphics = _graphics ?? (_graphics = Graphics.FromImage(bitmap));
var pixelWidth = Convert.ToInt32(width * 7); //7 pixels per excel column width
var fontSize = font.Size * 1.01f;
var drawingFont = new Font(font.Name, fontSize);
var size = graphics.MeasureString(text, drawingFont, pixelWidth, new StringFormat { FormatFlags = StringFormatFlags.MeasureTrailingSpaces });
//72 DPI and 96 points per inch. Excel height in points with max of 409 per Excel requirements.
return Math.Min(Convert.ToDouble(size.Height) * 72 / 96, 409);
}
I have used a workaround for this and I a had print area A:Q.
I copied merged cells value to column z.
set width of column z to merge cells width.
Then set auto row height true in format.
Hide the z column.
Set print area A:Q
Cons:
There are duplicate data. But we are okay since report is printing and not print z column.
Pros:
Row height works correctly not like calculation method.
Had to tweak the code a little bit by removing the multiplication factor at the return line. May be because i am using this code to get the width of the column.
ws1.Column(colIndx).Width * 7
The multiplication factor is the number of columns been merged.
I'm trying to use the chart control on a windows form and have it working, plotting some real time data, however before the data arrives nothing is displayed. I would like to show an empty graph with an X Y of 10 30 but still have the graph auto range if values go above this.
I cannot find a property to show the "blank" graph it this possible and if so how?
thanks
You can hide all data of a Series by making its line color Transparent. If you also set its LegendText to be " " all you can see are the Axis ticks. you can control them by adding a few Points and by setting the Minimum and Maximum values:
// short reference for our dummy:
Series S0 = chart1.Series[0];
// a simple type
S0.ChartType = SeriesChartType.Line;
// set 10 point with x-values going from 0-100 and y-values going from 1-10:
for (int i = 0; i < 100; i +=10) S0.Points.AddXY(i , i / 10);
// or add only a few, e.g. the first and last points:
//S0.Points.AddXY(100, 10);
//S0.Points.AddXY(0, 10);
// hide the line:
S0.Color = Color.Transparent;
// hide the legend text (it will still take up a little space, though)
S0.LegendText = " ";
// limit the axis to the target values
chart1.ChartAreas[0].AxisX.Maximum = 100;
chart1.ChartAreas[0].AxisX.Minimum = 0;
The result looks like an empty chart:
I am drawing a chart which I populate with the data I obtain from different procedures. I want to make two buttons to zoom in and out. I saw that I can use different functions from AxisX.ScaleView and I am playing a bit with those. I am almost there but I have a problem at the moment of drawing the chart:If you see the image 1, this is the chart after executing the different procedures and drawing it for the first time. When I do a zoom in and a zoom out, the last bars (Week 22 from image 2) are cut in half and doesn't go to its original size.
Does anyone have any idea how can I manipulate the start and end position for the Axis X in order to make the zoom? Does anyone know how to get the initian values of start and end of the Chart Area? I place the code of my function to make the zoom of the chart:
private void setSize(int zoom)
{
int blockSize = (Convert.ToInt32(tbZoom.Text) + zoom) / 100;
// set view range to [0,max]
chartReport.ChartAreas[0].AxisX.Minimum = 0;
chartReport.ChartAreas[0].AxisX.Maximum = chartReport.Series[0].Points.Count;
// enable autoscroll
chartReport.ChartAreas[0].CursorX.AutoScroll = true;
chartReport.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
// let's zoom to [0,blockSize] (e.g. [0,100])
chartReport.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
chartReport.ChartAreas[0].AxisX.ScaleView.SizeType = DateTimeIntervalType.Number;
int actualHeight = chartReport.Height;
int actualWidth = chartReport.Width;
int position = 0;
int size = blockSize;
chartReport.ChartAreas[0].AxisX.ScaleView.Zoom(position, size);
// disable zoom-reset button (only scrollbar's arrows are available)
chartReport.ChartAreas[0].AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.SmallScroll;
// set scrollbar small change to blockSize (e.g. 100)
chartReport.ChartAreas[0].AxisX.ScaleView.SmallScrollSize = blockSize;
tbZoom.Text = (blockSize * 100).ToString();
}
Your first line is setting the maximum of the axis wrong: chartReport.ChartAreas[0].AxisX.Maximum = chartReport.Series[0].Points.Count; sets it to 22, when it really should be 23 (based on the first image).
If your data will always look like this, simply add 1:
chartReport.ChartAreas[0].AxisX.Maximum = chartReport.Series[0].Points.Count + 1;
Unfortunately, using the automatic min/max values won't give you the actual values until the chart is actually drawn. If your chart has few DataPoints this isn't a problem, as you can just call chartReport.Refresh(); or something similar and then get the values from the axes. But, if you have a lot of points, the Refresh() will take a long time which is undesirable. In my extensive use of the charts, I wound up setting the axis ranges myself so I have full control, rather than using the automatic min/max values.
I have a Panel that I'm creating programmatically; additionally I'm adding several components to it.
One of these components is a Label which will contain user-generated content.
I don't know how tall the label should be, but it does have a fixed width.
How can I set the height so that it displays all the text, without changing the width?
Just use the AutoSize property, set it back to True.
Set the MaximumSize property to, say, (60, 0) so it can't grow horizontally, only vertically.
Use Graphics.MeasureString:
public SizeF MeasureString(
string text,
Font font,
int width
)
The width parameter specifies the
maximum value of the width component
of the returned SizeF structure
(Width). If the width parameter is
less than the actual width of the
string, the returned Width component
is truncated to a value representing
the maximum number of characters that
will fit within the specified width.
To accommodate the entire string, the
returned Height component is adjusted
to a value that allows displaying the
string with character wrap.
In other words, this function can calculate the height of your string based on its width.
If you have a label and you want have control over the the vertical fit, you can do the following:
MyLabel.MaximumSize = new Size(MyLabel.Width, 0)
MyLabel.Height = MyLabel.PreferredHeight
MyLabel.MaximumSize = new Size(0, 0)
This is useful for example if you have a label in a container that can be resized. In that case, you can set the Anchor property so that the label is resized horizontally but not vertically, and in the resize event, you can fit the height using the method above.
To avoid the vertical fitting to be interpreted as a new resize event, you can use a boolean:
bool _inVerticalFit = false;
And in the resize event:
if (_inVerticalFit) return;
_inVerticalFit = true;
MyLabel.MaximumSize = new Size(MyLabel.Width, 0)
MyLabel.Height = MyLabel.PreferredHeight
MyLabel.MaximumSize = new Size(0, 0)
_inVerticalFit = false;