I'd like to know how could I change the color of the date time axis of my d3 chartplotter.
The color that I want to change is the brown color and the white background color between the two bars.
If i do that :
It only changes the thing above the first brown bar.
Is it possible to change the color of these two bars ?
Curiously, I've happened to be trying to do the same thing. It turns out those colours are hard-coded in MayorDateTimeLabelProvider.cs (I've noted the lines in comments below). If you're using the compiled DLL then there is no way to change the values. Personally, D3 is so immature that I keep my own build of it and make changes to extend it as needed (such as in this case!).
public override UIElement[] CreateLabels(ITicksInfo<DateTime> ticksInfo)
{
object info = ticksInfo.Info;
var ticks = ticksInfo.Ticks;
UIElement[] res = new UIElement[ticks.Length - 1];
int labelsNum = 3;
if (info is DifferenceIn)
{
DifferenceIn diff = (DifferenceIn)info;
DateFormat = GetDateFormat(diff);
}
else if (info is MayorLabelsInfo)
{
MayorLabelsInfo mInfo = (MayorLabelsInfo)info;
DifferenceIn diff = (DifferenceIn)mInfo.Info;
DateFormat = GetDateFormat(diff);
labelsNum = mInfo.MayorLabelsCount + 1;
//DebugVerify.Is(labelsNum < 100);
}
DebugVerify.Is(ticks.Length < 10);
LabelTickInfo<DateTime> tickInfo = new LabelTickInfo<DateTime>();
for (int i = 0; i < ticks.Length - 1; i++)
{
tickInfo.Info = info;
tickInfo.Tick = ticks[i];
string tickText = GetString(tickInfo);
Grid grid = new Grid
{
Background = Brushes.Beige // **** HARD CODED HERE
};
Rectangle rect = new Rectangle
{
Stroke = Brushes.Peru, // **** AND HERE
StrokeThickness = 2
};
Grid.SetColumn(rect, 0);
Grid.SetColumnSpan(rect, labelsNum);
for (int j = 0; j < labelsNum; j++)
{
grid.ColumnDefinitions.Add(new ColumnDefinition());
}
grid.Children.Add(rect);
for (int j = 0; j < labelsNum; j++)
{
var tb = new TextBlock
{
Text = tickText,
HorizontalAlignment = HorizontalAlignment.Center,
Margin = new Thickness(0, 3, 0, 3)
};
Grid.SetColumn(tb, j);
grid.Children.Add(tb);
}
ApplyCustomView(tickInfo, grid);
res[i] = grid;
}
return res;
}
Related
I'm creating slides for a PowerPoint Presentation using C#. I've so far managed to create tables for a slide using Shape.AddTable method, and the table is created with a default style. I want to be able to change color and line weight for each cell, but I can't seem to find the method to add borders to the cells.
I've tried using learn.microsoft for help, but no luck:
https://learn.microsoft.com/en-us/previous-versions/office/office-12/ff760048(v=office.12)
My code:
int n_rows = 28;
int n_cols = 8;
int row_height = 12;
int font_size = 6;
int top_margin = 1;
int left_margin = 3;
PowerPoint.Shape tb = slide.Shapes.AddTable(n_rows, n_cols, 40, 150, 870, 200);
for (int i = 1; i < n_cols + 1; i++)
{
for(int j=1;j< n_rows + 1;j++)
{
tb.Table.Cell(j, i).Shape.TextFrame.TextRange.Font.Size = font_size;
tb.Table.Cell(j, i).Shape.TextFrame.TextRange.Font.Bold = Office.MsoTriState.msoFalse;
tb.Table.Cell(j, i).Shape.TextFrame.TextRange.Text = "test";
tb.Table.Cell(j, i).Shape.TextFrame.MarginBottom = 0;
tb.Table.Cell(j, i).Shape.TextFrame.MarginTop = top_margin;
tb.Table.Cell(j, i).Shape.TextFrame.MarginLeft = left_margin;
tb.Table.Cell(j, i).Shape.TextFrame.MarginRight = 0;
tb.Table.Cell(j, i).Shape.Fill.ForeColor.RGB = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.White);
}
}
I found out I had to add Dashstyle and Forecolor property to the Borders like this:
tb.Table.Cell(j, i).Borders[PowerPoint.PpBorderType.ppBorderTop].DashStyle = Office.MsoLineDashStyle.msoLineSolid;
tb.Table.Cell(j, i).Borders[PowerPoint.PpBorderType.ppBorderTop].ForeColor.RGB = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Black);
tb.Table.Cell(j, i).Borders[PowerPoint.PpBorderType.ppBorderTop].Weight = 0.2f;
Now it works!
I'm creating a boardgame app with UWP and C#. Currently my board is defined as a 2D array that grows as the tiles are placed. I'd like to be able to have a grid that grew with the array. I also wanted the empty spaces in the grid to be defined as buttons to be able to place the tile in the grid with a click.
I tried using this method in the backend code based on an answer I saw on this link but I don't think I'm doing things the right way.
public Grid GridGenerator(int rows, int cols, int[,] map)
{
Grid grid = new Grid();
grid.Margin = new Thickness(50, 50, 50, 50);
grid.Background = new SolidColorBrush(Windows.UI.Colors.Brown);
grid.HorizontalAlignment = HorizontalAlignment.Center;
grid.VerticalAlignment = VerticalAlignment.Center;
for (int i = 0; i < rows; i++)
{
RowDefinition Row = new RowDefinition();
Row.Height = new GridLength(0, GridUnitType.Auto);
grid.RowDefinitions.Add(Row);
for (int j = 0; j < cols; j++)
{
ColumnDefinition column = new ColumnDefinition();
column.Width = new GridLength(0, GridUnitType.Auto);
grid.ColumnDefinitions.Add(column);
if (map[i, j] == 0)
{
Button button = new Button();
button.MinHeight = 30;
button.MinWidth = 30;
button.Background = new SolidColorBrush(Windows.UI.Colors.AliceBlue);
button.Name = i.ToString() + j.ToString();
grid.Children.Add(button);
Grid.SetColumn(button, j);
}
else
{
TextBlock text = new TextBlock();
text.Text = map[i, j].ToString();
text.HorizontalTextAlignment = (TextAlignment)HorizontalAlignment.Center;
text.HorizontalAlignment = HorizontalAlignment.Center;
text.VerticalAlignment = VerticalAlignment.Center;
grid.Children.Add(text);
Grid.SetColumn(text, j);
}
}
}
It seems you are adding too many ColumnDefinitions through the nested loop. Try writing each step separately so that you can grasp what to do.
public Grid GridGenerator(int rows, int cols, int[,] map)
{
Grid grid = new Grid();
:
// 1.Prepare RowDefinitions
for (int i = 0; i < rows; i++)
{
RowDefinition Row = new RowDefinition();
Row.Height = new GridLength(0, GridUnitType.Auto);
grid.RowDefinitions.Add(Row);
}
// 2.Prepare ColumnDefinitions
for (int j = 0; j < cols; j++)
{
ColumnDefinition column = new ColumnDefinition();
column.Width = new GridLength(0, GridUnitType.Auto);
grid.ColumnDefinitions.Add(column);
}
// 3.Add each item and set row and column.
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (map[i, j] == 0)
{
Button button = new Button();
:
grid.Children.Add(button);
Grid.SetColumn(button, j);
Grid.SetRow(button, i); // Set row too!
}
:
}
}
return grid;
}
Appendix
How to display the grid generated in code behind:To display it, you need to put it in XAML tree. For example, if you'd like to show it in another Grid (named "LayoutRoot") in XAML page,
<Grid x:Name="LayoutRoot"></Grid>
add it to LayoutRoot.Children in the code behind.
Grid board_grid = GridGenerator(5, 5, map);
LayoutRoot.Children.Add(board_grid);
EDIT:
Okay so for clarity I will improve my information a bit more:
I have a TableLayoutView (I will call this tlv) that has 5 fixed columns, and x + 2 rows. The first row of tlv contains labels in each cell for header purposes. I dynamically add more rows onto tlv and so that it why it has a variable amount of rows (plus the initial header row which is never removed).
As another tiny small complication, I also keep an empty row entry at the bottom of tlv which I must keep because I use it for other functionality.
To visualise what I have just said, this is an example of tlv consisting with 4 entries (numbered), the header row (H's) and the placeholder row (P's).
HHHHH
11111
22222
33333
44444
PPPPP
I want to go from that, to say, if I wanted to swap entry 2 and 3 the output would be:
HHHHH
11111
33333
22222
44444
PPPPP
The code I have so far is as follows:
for (int j = 0; j < 5; j++)
{
TableLayoutPanelCellPosition tablePosition1 = new
TableLayoutPanelCellPosition(j, rowIndex + 1);
Control moveControl1 = queuedFiles.GetControlFromPosition(j, rowIndex);
queuedFiles.SetCellPosition(moveControl1, tablePosition1);
TableLayoutPanelCellPosition tablePosition2 = new
TableLayoutPanelCellPosition(j, rowIndex);
Control moveControl2 = queuedFiles.GetControlFromPosition(j, rowIndex + 1);
queuedFiles.SetCellPosition(moveControl2, tablePosition2);
if (j.Equals(0))
{
moveControl1.Text = (rowIndex + 1).ToString();
moveControl2.Text = (rowIndex).ToString();
}
}
However this code doesn't work and for the example above it produces:
HHHHH
11111
33222
22333
44444
PPPPP
What I believe is happening is tlv is automatically organising it's contents itself during the process of moving them around (maybe to fill vacant spaces?).
rowIndex above is the index of the target row which must be swapped with the row below it. I don't need to worry about checking if there is only 1 row or if it is the last row because I have done that already. Ignore changing the text too, I just need a pointer as to how I can achieve the intended result!
Thank you for absolutely any help you can give :)
The following code does the job:
Code
using System;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// some content
var panel = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = 5,
RowCount = 2
};
for (var y = 0; y < 2; y++)
for (var x = 0; x < 5; x++)
{
var control = new Button {Text = $#"X = {x}, Y = {y}"};
panel.Controls.Add(control, x, y);
}
// swap button
var button = new Button
{
Dock = DockStyle.Fill,
Text = #"Clicky !"
};
button.Click += (o, args) =>
{
var dictionary = panel.Controls
.Cast<Control>()
.ToDictionary(k => k, v => panel.GetCellPosition(v));
foreach (var pair in dictionary)
{
var position = pair.Value;
position.Row ^= 1; // simple row swap
panel.SetCellPosition(pair.Key, position);
}
};
// add to form
var container = new SplitContainer
{
Dock = DockStyle.Fill,
Orientation = Orientation.Horizontal,
SplitterWidth = 5,
BorderStyle = BorderStyle.Fixed3D
};
container.Panel1.Controls.Add(panel);
container.Panel2.Controls.Add(button);
Controls.Add(container);
}
}
}
Before
After
Note
Next time you ask a question, post a Minimal, Complete, and Verifiable example to maximize your chances of getting an answer !
As on why your code didn't work, see previous sentence, e.g what was rowIndex etc ?
Edit
using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
const int cols = 5;
const int rows = 6;
// setup layout
var tlp = new TableLayoutPanel
{
ColumnCount = cols,
RowCount = rows,
Dock = DockStyle.Fill,
GrowStyle = TableLayoutPanelGrowStyle.FixedSize
};
for (var i = 0; i < cols; i++)
tlp.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100.0f / cols));
// add header
var label = new Label
{
Text = #"My Header",
BackColor = Color.Red,
Dock = DockStyle.Fill,
TextAlign = ContentAlignment.MiddleCenter
};
tlp.Controls.Add(label);
tlp.SetColumn(label, 0);
tlp.SetRow(label, 0);
tlp.SetColumnSpan(label, cols);
// add some cells
var yMin = 1;
var yMax = 5;
var xMin = 0;
var xMax = cols;
for (var y = yMin; y < yMax; y++)
for (var x = xMin; x < xMax; x++)
{
var color = Color.FromArgb(
255 / (xMax - xMin) * (x - xMin),
128,
255 / (yMax - yMin) * (y - yMin)
);
var label1 = new Label
{
Text = $#"X = {x}, Y = {y}",
BackColor = color,
ForeColor = Color.White,
Dock = DockStyle.Fill,
TextAlign = ContentAlignment.MiddleCenter,
Margin = DefaultMargin
};
tlp.Controls.Add(label1, x, y);
}
// add swapper
var button = new Button
{
Text = #"Clicky !",
Dock = DockStyle.Fill
};
button.Click += (o, args) =>
{
var srcRow = 2;
var tgtRow = 3;
var controls = tlp.Controls.Cast<Control>().ToArray();
var array1 = controls.Where(s => tlp.GetRow(s) == srcRow).ToArray();
var array2 = controls.Where(s => tlp.GetRow(s) == tgtRow).ToArray();
foreach (var control in array1)
tlp.SetCellPosition(control, new TableLayoutPanelCellPosition(tlp.GetColumn(control), tgtRow));
foreach (var control in array2)
tlp.SetCellPosition(control, new TableLayoutPanelCellPosition(tlp.GetColumn(control), srcRow));
};
// pack things up
var sc = new SplitContainer
{
Orientation = Orientation.Horizontal,
BorderStyle = BorderStyle.Fixed3D,
Dock = DockStyle.Fill
};
sc.Panel1.Controls.Add(tlp);
sc.Panel2.Controls.Add(button);
Controls.Add(sc);
}
}
}
i am using a for loop to add 198 items, half numbers and half images for an app just to get familiar with xamarin forms but am unable to switch from vertical to horizontal. the desired output is to have 4 images with their serial number in one line.
EDIT: i am unable to get it to display in multiple lines
Image[] show = new Image[100];
for(int i=0;i<100;i++)
{
show[i]=new Image{ Aspect = Aspect.AspectFit };
show[i].WidthRequest = 30;
show[i].HeightRequest = 30;
show[i].Source = images[i];
}
for (int i=0;i<99;i++)
{
if (i % 4 == 0)
{
layout.HorizontalOptions = LayoutOptions.Start;
layout.Spacing = 15;
layout.Orientation = StackOrientation.Vertical;
layout.Children.Add(new Label { Text = (i+1).ToString() });
layout.Spacing = 10;
layout.Children.Add(show[i]);
}
else
{
layout.HorizontalOptions = LayoutOptions.StartAndExpand;
layout.Spacing = 10;
layout.Orientation = StackOrientation.Horizontal;
layout.Children.Add(new Label { Text = (i+1).ToString() });
layout.Children.Add(show[i]);
}
}
This is the current outputOutput
I would recommend using a grid, but to use layouts you would need something more like this:
var outerLayout = new StackLayout {Orientation = StackOrientation.Vertical};
var innerLayout = new StackLayout();
for (int i = 0; i < 99; i++)
{
if (i%4 == 0)
{
if (i != 0)
outerLayout.Children.Add(innerLayout);
innerLayout = new StackLayout {Orientation = StackOrientation.Horizontal};
}
innerLayout.Children.Add(new Label { Text = (i + 1).ToString() });
innerLayout..Children.Add(show[i]);
}
outerLayout.Children.Add(innerLayout);
MainPage = new ContentPage {Content = outerLayout};
This creates an outer vertical layout to hold all the horizontal layouts, then creates a horizontal layout for each group that you want displayed horizontally.
i have a working DLL where i have one function to add arrays to a list and another function that shows all list-arrays in a ZED-Graph-diagram. All arrays have the same size.
Currently the x-axis is shown in points from 0 to 1024.
Question is: What do i have to change to display the x-axis in time?
I have the value "Intervall" (time between two points) that i can pass into the function.
Thanks for the help.
Here is what i have so far:
public void AddGraph(double[] Values, string LegendName)
{
int i = 0;
PointPairList list = new PointPairList();
for (i = 0; i < Values.Length; i++)
{
list.Add(i, Values[i]);
}
if (i > MaxXAxis)
MaxXAxis = i;
SList.Add(list);
SListColor.Add(Color.Black);
SListName.Add(LegendName);
}
public void ShowDiagram(string Title, string XAxisName, string YAxisName, int Timeout_ms)
{
ZedGraph.ZedGraphControl zgc = new ZedGraphControl();
GraphPane myPane = zgc.GraphPane;
LineItem myCurve = null;
// Set the titles and axis labels
myPane.Title.Text = Title;
myPane.XAxis.Title.Text = XAxisName;
myPane.YAxis.Title.Text = YAxisName;
for (int i = 0; i < SList.Count(); i++)
{
myCurve = myPane.AddCurve(SListName[i], SList[i], SListColor[i], SymbolType.None);
myCurve.Line.Width = 2;
}
// Add gridlines to the plot, and make them gray
myPane.XAxis.MinorGrid.IsVisible = true;
myPane.YAxis.MinorGrid.IsVisible = true;
myPane.XAxis.MinorGrid.Color = Color.LightGray;
myPane.YAxis.MinorGrid.Color = Color.LightGray;
myPane.XAxis.MinorGrid.DashOff = 0;
myPane.YAxis.MinorGrid.DashOff = 0;
myPane.XAxis.MajorGrid.IsVisible = true;
myPane.YAxis.MajorGrid.IsVisible = true;
myPane.XAxis.MajorGrid.Color = Color.Gray;
myPane.YAxis.MajorGrid.Color = Color.Gray;
myPane.XAxis.MajorGrid.DashOff = 0;
myPane.YAxis.MajorGrid.DashOff = 0;
// Move Legend to buttom
myPane.Legend.Position = LegendPos.Bottom;
zgc.AxisChange();
myPane.XAxis.Scale.Max = MaxXAxis;
zgc.Location = new Point(0, 0);
zgc.Size = new Size(panel_diagramm.ClientRectangle.Width, panel_diagramm.ClientRectangle.Height);
panel_diagramm.Controls.Add(zgc);
}
This is my first time posting so I apologize for not putting it in a better format.
The following allows you to setup your x-axis to display time:
myPane.XAxis.Type = AxisType.Date;
myPane.XAxis.Title.Text = "Time (HH:MM:SS)";
myPane.XAxis.Scale.Format = "HH:mm:ss";
myPane.XAxis.Scale.MajorUnit = DateUnit.Minute;
myPane.XAxis.Scale.MinorUnit = DateUnit.Minute;
myPane.XAxis.Scale.Min = DateTime.Now.Subtract(new TimeSpan(0, 0, 10, 0, 0).ToOADate();
myPane.XAxis.Scale.Max = DateTime.Now.ToOADate();