I have a Xamarin C# IOS app I wrote, using a uitableviewsource to display an unordered list. Everything looks fine until I scroll up, then the text goes up into the header and when I scroll back down it disappears.
The code for the header is as follows
public override UIView GetViewForHeader(UITableView tableView, nint section)
{
UIView view = new UIView(new Rectangle(0, 65, 320, 90));
UILabel label = new UILabel
{
Opaque = true,
TextColor = UIColor.Black, //.FromRGB(190, 0, 0);
Font = UIFont.FromName("Helvetica-Bold", 16f),
Frame = new RectangleF(12, 70, 375, 20),
Text = "View Mileage",
TextAlignment = UITextAlignment.Center
};
view.AddSubview(label);
UIButton buttonRect = new UIButton
{
Opaque = true,
BackgroundColor = UIColor.FromRGB(191, 187, 189),
Font = UIFont.FromName("Helvetica-Bold", 16f),
Frame = new CGRect(145, 19, 100, 40)
};
buttonRect.SetTitle("Main Menu", UIControlState.Normal);
buttonRect.SetTitleColor(UIColor.Black, UIControlState.Normal);
buttonRect.HorizontalAlignment = UIControlContentHorizontalAlignment.Center;
buttonRect.VerticalAlignment = UIControlContentVerticalAlignment.Center;
buttonRect.TouchUpInside += delegate
{
UIStoryboard Storyboard = UIStoryboard.FromName("Main", null);
var webController = Storyboard.InstantiateViewController("MainMenuViewController") as MainMenuViewController;
Window = new UIWindow(UIScreen.MainScreen.Bounds);
this.Window.RootViewController = webController;
this.Window.MakeKeyAndVisible();
};
view.AddSubview(buttonRect);
UIButton buttonDate = new UIButton
{
Opaque = true,
BackgroundColor = UIColor.Brown,
Font = UIFont.FromName("Helvetica-Bold", 13f),
Frame = new CGRect(35, 105, 50, 25)
};
buttonDate.SetTitle("Date", UIControlState.Normal);
buttonDate.SetTitleColor(UIColor.White, UIControlState.Normal);
buttonDate.HorizontalAlignment = UIControlContentHorizontalAlignment.Center;
buttonDate.VerticalAlignment = UIControlContentVerticalAlignment.Center;
buttonDate.TouchUpInside += delegate
{
dataList.Sort((x, y) => x.Date.CompareTo(y.Date));
if (dateCounter % 2 != 0)
dataList.Reverse();
tableView.ReloadData();
dateCounter++;
};
view.AddSubview(buttonDate);
UIButton buttonMiles = new UIButton
{
Opaque = true,
BackgroundColor = UIColor.Brown,
Font = UIFont.FromName("Helvetica-Bold", 13f),
Frame = new CGRect(100, 105, 50, 25)
};
buttonMiles.SetTitle("Miles", UIControlState.Normal);
buttonMiles.SetTitleColor(UIColor.White, UIControlState.Normal);
buttonMiles.HorizontalAlignment = UIControlContentHorizontalAlignment.Center;
buttonMiles.VerticalAlignment = UIControlContentVerticalAlignment.Center;
buttonMiles.TouchUpInside += delegate
{
dataList.Sort((x, y) => x.Miles.CompareTo(y.Miles));
if (milesCounter % 2 == 0)
dataList.Reverse();
tableView.ReloadData();
milesCounter++;
};
view.AddSubview(buttonMiles);
UIButton buttonGas = new UIButton
{
Opaque = true,
BackgroundColor = UIColor.Brown,
Font = UIFont.FromName("Helvetica-Bold", 13f),
Frame = new CGRect(174, 105, 50, 25)
};
buttonGas.SetTitle("Gas", UIControlState.Normal);
buttonGas.SetTitleColor(UIColor.White, UIControlState.Normal);
buttonGas.HorizontalAlignment = UIControlContentHorizontalAlignment.Center;
buttonGas.VerticalAlignment = UIControlContentVerticalAlignment.Center;
buttonGas.TouchUpInside += delegate
{
dataList.Sort((x, y) => x.Gas.CompareTo(y.Gas));
if (gasCounter % 2 == 0)
dataList.Reverse();
tableView.ReloadData();
gasCounter++;
};
view.AddSubview(buttonGas);
UIButton buttonMpg = new UIButton
{
Opaque = true,
BackgroundColor = UIColor.Brown,
Font = UIFont.FromName("Helvetica-Bold", 13f),
Frame = new CGRect(244, 105, 50, 25)
};
buttonMpg.SetTitle("MPG", UIControlState.Normal);
buttonMpg.SetTitleColor(UIColor.White, UIControlState.Normal);
buttonMpg.HorizontalAlignment = UIControlContentHorizontalAlignment.Center;
buttonMpg.VerticalAlignment = UIControlContentVerticalAlignment.Center;
buttonMpg.TouchUpInside += delegate
{
dataList.Sort((x, y) => x.MPG.CompareTo(y.MPG));
if (mpgCounter % 2 == 0)
dataList.Reverse();
tableView.ReloadData();
mpgCounter++;
};
view.AddSubview(buttonMpg);
UIButton buttonCost = new UIButton
{
Opaque = true,
BackgroundColor = UIColor.Brown,
Font = UIFont.FromName("Helvetica-Bold", 13f),
Frame = new CGRect(314, 105, 50, 25)
};
buttonCost.SetTitle("Cost", UIControlState.Normal);
buttonCost.SetTitleColor(UIColor.White, UIControlState.Normal);
buttonCost.HorizontalAlignment = UIControlContentHorizontalAlignment.Center;
buttonCost.VerticalAlignment = UIControlContentVerticalAlignment.Center;
buttonCost.TouchUpInside += delegate
{
dataList.Sort((x, y) => x.Price.CompareTo(y.Price));
if (costCounter % 2 == 0)
dataList.Reverse();
tableView.ReloadData();
costCounter++;
};
view.AddSubview(buttonCost);
return view;
}
I am populating the table view using a UITableViewCell as follows;
public void SetData(string str0, string str1, string str2, string str3, int id, string str4)
{
lbC0.Text = str0;
lbC1.Text = str1;
lbC2.Text = str2;
lbC3.Text = str3;
lbcst.Text = str4;
lbId.Text = id.ToString();
}
public override void LayoutSubviews()
{
nfloat lbWidth = Bounds.Width / 4;
nfloat lbWidth2 = lbWidth - 35;
nfloat lbWidth3 = lbWidth2 + 70;
nfloat lbWidth4 = lbWidth3 + 70;
nfloat lbWidth5 = lbWidth4 + 65;
nfloat lbWidth6 = lbWidth5 + 75;
nfloat lbHeight = this.Bounds.Height;
if (lbC0 != null)
{
lbC0.Frame = new CGRect(2, 55, lbWidth, lbHeight);
lbC1.Frame = new CGRect(lbWidth2, 55, lbWidth, lbHeight);
lbC2.Frame = new CGRect(lbWidth3, 55, lbWidth, lbHeight);
lbC3.Frame = new CGRect(lbWidth4, 55, lbWidth, lbHeight);
lbcst.Frame = new CGRect(lbWidth5, 55, lbWidth, lbHeight);
}
}
Any help would be greatly appreciated.
Thanks
I spent weeks searching for an answer. What I finally found was I needed my subviews bounds within my TableViewCell’s bounds. This was all well and good, but I couldn’t figure out how to make it so. I tried everything I found, all to no avail. What finally ended up solving it for me was this. In my LayoutSubviews method, when setting the height of the subview, I subtracted 100 from Bounds.Height and that fixed it, it now scrolls up and down. How simple a fix... how hard to find
Here is the code I changed;
public override void LayoutSubviews()
{
nfloat lbWidth = Bounds.Width / 4;
nfloat lbWidth2 = lbWidth - 35;
nfloat lbWidth3 = lbWidth2 + 70;
nfloat lbWidth4 = lbWidth3 + 70;
nfloat lbWidth5 = lbWidth4 + 65;
nfloat lbWidth6 = lbWidth5 + 75;
-->nfloat lbHeight = this.Bounds.Height - 100;<--
if (lbC0 != null)
{
lbC0.Frame = new CGRect(2, 55, lbWidth, lbHeight);
lbC1.Frame = new CGRect(lbWidth2, 55, lbWidth, lbHeight);
lbC2.Frame = new CGRect(lbWidth3, 55, lbWidth, lbHeight);
lbC3.Frame = new CGRect(lbWidth4, 55, lbWidth, lbHeight);
lbcst.Frame = new CGRect(lbWidth5, 55, lbWidth, lbHeight);
}
}
Related
I am new in xamarin.ios I want to resize the row height according to the content length. How can I do that.
Here is my ViewController.Cs
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
nfloat _width = UIScreen.MainScreen.Bounds.Width / 3;
DataBinding();
_table = new UITableView(new CGRect(0, 0, View.Frame.Width, View.Frame.Height));
_table.Source = new DetailsTableViewSource(_caseDesign);
_table.RowHeight = UITableView.AutomaticDimension;
_table.EstimatedRowHeight = 100f;
_table.ReloadData();
View.AddSubview(_table);
}
DetailsTableViewSource.Cs
public class DetailsTableViewSource : UITableViewSource
{
public List<CaseDetails> tabledata;
public DetailsTableViewSource(List<CaseDetails> items)
{
tabledata = items;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
NSString cellIdentifier = new NSString();
var cell = tableView.DequeueReusableCell(cellIdentifier) as CaseDetailsTableCell;
if (cell == null)
cell = new CaseDetailsTableCell(cellIdentifier);
cell.UpdateCell(tabledata[indexPath.Row].Title
, tabledata[indexPath.Row].Description
);
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return tabledata.Count;
}
}
CaseDetailsTableCell.cs
public class CaseDetailsTableCell:UITableViewCell
{
UILabel _qst1, _answer1, _seperator;
nfloat _width;
public CaseDetailsTableCell(NSString cellId) : base(UITableViewCellStyle.Default, cellId)
{
_width = UIScreen.MainScreen.Bounds.Width / 3;
_qst1 = new UILabel();
_qst1.Font = _qst1.Font.WithSize(15);
_seperator = new UILabel();
_seperator.TextAlignment = UITextAlignment.Center;
_seperator.Text = ":";
_seperator.Font = _seperator.Font.WithSize(20);
_answer1 = new UILabel();
_answer1.Font = _answer1.Font.WithSize(15);
ContentView.AddSubviews(new UIView[] { _qst1, _seperator, _answer1 });
}
public void UpdateCell(string Quetion, string Answer)
{
_qst1.Text = Quetion;
_answer1.Text = Answer;
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
_qst1.Frame = new CGRect(10, 10, _width + 10, 30);
_qst1.Lines = 0;
_qst1.SizeToFit();
_qst1.LineBreakMode = UILineBreakMode.Clip;
_qst1.TextAlignment = UITextAlignment.Left;
_answer1.Frame = new CGRect(_width * 2, 10, UIScreen.MainScreen.Bounds.Width / 3 - 10, 30);
_answer1.SizeToFit();
_answer1.TextAlignment = UITextAlignment.Justified;
_answer1.LineBreakMode = UILineBreakMode.WordWrap;
_seperator.Frame = new CGRect(_width + 10, 10, UIScreen.MainScreen.Bounds.Width / 3, 30);
// _date.Frame = new CGRect(17, 50, 50, 20);
}
}
I want to bind some data into the table and the length of the each item is different, according to the length of the data, the row height is automatically resize . How can i do that.
Now the table look like this
I want the table like this
If you want to automatically resize the tableView's row height, you should use autoLayout to place your controls in the cell instead of the Frame. Also put the constraints code in the constructor of the cell will be better:
public CaseDetailsTableCell(NSString cellId) : base(UITableViewCellStyle.Default, cellId)
{
_width = UIScreen.MainScreen.Bounds.Width / 3;
_qst1 = new UILabel();
_qst1.Font = _qst1.Font.WithSize(15);
_seperator = new UILabel();
_seperator.TextAlignment = UITextAlignment.Center;
_seperator.Text = ":";
_seperator.Font = _seperator.Font.WithSize(20);
_answer1 = new UILabel();
_answer1.Font = _answer1.Font.WithSize(15);
ContentView.AddSubviews(new UIView[] { _qst1, _seperator, _answer1 });
// Disable this to enable autoLayout
_qst1.TranslatesAutoresizingMaskIntoConstraints = false;
var qstLeading = NSLayoutConstraint.Create(_qst1, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Leading, 1, 10);
var qstTop = NSLayoutConstraint.Create(_qst1, NSLayoutAttribute.Top, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Top, 1, 10);
var qstWidth = NSLayoutConstraint.Create(_qst1, NSLayoutAttribute.Width, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 0, _width + 10);
var qstBottom = NSLayoutConstraint.Create(_qst1, NSLayoutAttribute.Bottom, NSLayoutRelation.LessThanOrEqual, ContentView, NSLayoutAttribute.Bottom, 1, -10);
_qst1.Lines = 0;
_qst1.SizeToFit();
_qst1.LineBreakMode = UILineBreakMode.Clip;
_qst1.TextAlignment = UITextAlignment.Left;
_qst1.BackgroundColor = UIColor.Blue;
_seperator.TranslatesAutoresizingMaskIntoConstraints = false;
var sepLeading = NSLayoutConstraint.Create(_seperator, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, _qst1, NSLayoutAttribute.Trailing, 1, 10);
var sepTop = NSLayoutConstraint.Create(_seperator, NSLayoutAttribute.Top, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Top, 1, 10);
var sepWidth = NSLayoutConstraint.Create(_seperator, NSLayoutAttribute.Width, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 0, UIScreen.MainScreen.Bounds.Width / 3);
_seperator.BackgroundColor = UIColor.Yellow;
_answer1.TranslatesAutoresizingMaskIntoConstraints = false;
var ansLeading = NSLayoutConstraint.Create(_answer1, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, _seperator, NSLayoutAttribute.Trailing, 1, 10);
var ansTop = NSLayoutConstraint.Create(_answer1, NSLayoutAttribute.Top, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Top, 1, 10);
var ansTrailing = NSLayoutConstraint.Create(_answer1, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Trailing, 1, -10);
var ansBottom = NSLayoutConstraint.Create(_answer1, NSLayoutAttribute.Bottom, NSLayoutRelation.LessThanOrEqual, ContentView, NSLayoutAttribute.Bottom, 1, -10);
_answer1.SizeToFit();
_answer1.TextAlignment = UITextAlignment.Justified;
_answer1.LineBreakMode = UILineBreakMode.WordWrap;
_answer1.BackgroundColor = UIColor.Red;
_answer1.Lines = 0;
ContentView.AddConstraints(new NSLayoutConstraint[] { qstTop, qstLeading, qstWidth, qstBottom, sepLeading, sepTop, sepWidth, ansLeading, ansTop, ansTrailing, ansBottom });
}
Here I add the LessThanOrEqual NSLayoutRelation to bottom constraint of the _qst1 and _answer1 labels, the cell will adjust its height depending on the tallest one. You can adjust the constraints to fit your requirements.
I am a beginner in xamarin ios, I want to create a table with 3 columns and multiple rows, and the no of row is depends on the data coming from the API .How can I do this...
Please help me...
I want to create the table like this...
You can simulate drawing the chart by following steps.
Custom TableHeaderView with three black rectangle ,just need add three label with its black border.
Do the same work as step1 with TableViewCell, and then place a textfield in first rectangle, place a button and a label in second rectangle,place two button in third rectangle.
Sample Code
TableHeaderView
public class headerView : UIView
{
public headerView()
{
this.Frame = new CGRect(0, 0, UIScreen.MainScreen.Bounds.Width, 50);
nfloat width = UIScreen.MainScreen.Bounds.Width / 3;
UILabel title = new UILabel();
title.Text = "Title";
title.TextColor = UIColor.Black;
title.TextAlignment = UITextAlignment.Center;
title.Font = UIFont.SystemFontOfSize(20);
title.Layer.BorderColor = UIColor.Black.CGColor;
title.Layer.BorderWidth = 1;
title.Frame = new CGRect(0, 0, width, 50);
this.Add(title);
UILabel File = new UILabel();
File.Text = "File";
File.TextColor = UIColor.Black;
File.TextAlignment = UITextAlignment.Center;
File.Font = UIFont.SystemFontOfSize(20);
File.Layer.BorderColor = UIColor.Black.CGColor;
File.Layer.BorderWidth = 1;
File.Frame = new CGRect(width, 0, UIScreen.MainScreen.Bounds.Width / 3, 50);
this.Add(File);
UILabel Option = new UILabel();
Option.Text = "Option";
Option.TextColor = UIColor.Black;
Option.TextAlignment = UITextAlignment.Center;
Option.Font = UIFont.SystemFontOfSize(20);
Option.Layer.BorderColor = UIColor.Black.CGColor;
Option.Layer.BorderWidth = 1;
Option.Frame = new CGRect(width * 2, 0, UIScreen.MainScreen.Bounds.Width / 3, 50);
this.Add(Option);
}
}
table.TableHeaderView = new headerView();
TableViewCell
public CustomVegeCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
nfloat width = UIScreen.MainScreen.Bounds.Width / 3;
UIView headingLabel = new UIView();
headingLabel.Layer.BorderColor = UIColor.Black.CGColor;
headingLabel.Layer.BorderWidth = 1;
headingLabel.Frame = new CGRect(0, 0, width, 100);
UIView subheadingLabel = new UIView();
subheadingLabel.Layer.BorderColor = UIColor.Black.CGColor;
subheadingLabel.Layer.BorderWidth = 1;
subheadingLabel.Frame = new CGRect(width, 0, width, 100);
UIView imageView = new UIView();
imageView.Layer.BorderColor = UIColor.Black.CGColor;
imageView.Layer.BorderWidth = 1;
imageView.Frame = new CGRect(width *2, 0, width, 100);
ContentView.Add (headingLabel);
ContentView.Add (subheadingLabel);
ContentView.Add (imageView);
///add additional control here
}
I have a couple of problems with a MSChart plotted in a Winform.
I can't get axis Y2 values displayed on the right hand side of the chart, which should be the default - similar to this question
the stripline won't plot, and
is it possible to line up the zero values of axes Y1 and Y2?
Thanks for any help.
ChartArea TestChartArea = new ChartArea();
public void CreateChartArea()
{
TestChartArea.Name = "TestChartArea";
TestChartArea.BackColor = Color.LightGreen;
TestChartArea.Position = new ElementPosition { Height = 100, Width = 80, X = 2, Y = 5 };
//TestChartArea.Position = new ElementPosition { Auto = true };
TestChartArea.AxisY = new Axis
{
Enabled = AxisEnabled.True,
IsLabelAutoFit = true,
IsMarginVisible = true,
LabelStyle = new LabelStyle { Format = "P2", ForeColor = Color.DarkBlue, Font = new Font("Arial", 10, FontStyle.Regular) },
LineColor = Color.Black,
MajorGrid = new Grid { LineColor = Color.White, LineDashStyle = ChartDashStyle.Solid },
MajorTickMark = new TickMark { LineColor = Color.Black }
};
TestChartArea.AxisY2 = new Axis
{
Enabled = AxisEnabled.True,
IsLabelAutoFit = true,
IsMarginVisible = true,
LabelStyle = new LabelStyle { Format = "P2", ForeColor = Color.DarkBlue, Font = new Font("Arial", 10, FontStyle.Regular) },
LineColor = Color.Transparent,
MajorGrid = new Grid { LineColor = Color.Yellow, LineDashStyle = ChartDashStyle.Solid },
MajorTickMark = new TickMark { LineColor = Color.Blue }
};
TestChartArea.AxisX = new Axis
{
Enabled = AxisEnabled.True,
Crossing = 0,
LineWidth = 1,
IsLabelAutoFit = true,
IsMarginVisible = false,
LabelStyle = new LabelStyle { Angle=-45,Format = "N0", ForeColor = Color.Black, Font = new Font("Arial", 8, FontStyle.Regular) },
LineColor = Color.Black,
MajorGrid = new Grid { LineColor = Color.White, LineDashStyle = ChartDashStyle.Solid },
MajorTickMark = new TickMark { LineColor = Color.LightGray, Size = 4.0f },
Name="Spot"
};
}
public void PlotChart()
{
int[] Xseries = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
double[] AXJO = { 0.0025, 0.0015, -0.001, 0.002, 0.0045, -0.002, -0.003, 0.0001, -0.004, -0.0075 };
double[] ES = { 0.0020, 0.0010, -0.0005, 0.003, 0.0025, -0.001, -0.0015, 0.0005, -0.0032, -0.006 };
double[] Diff = new double[10];
// pair return
for (int i = 0; i < 10; i++)
{
Diff[i] = AXJO[i] - ES[i];
}
TestChart.BackColor = Color.LightGoldenrodYellow;
TestChart.BackSecondaryColor = Color.LightBlue;
if (TestChart.Series.IsUniqueName("AXJO"))
{
TestChart.Series.Add("AXJO");
TestChart.Series["AXJO"].YAxisType = AxisType.Primary;
TestChart.Series["AXJO"].Color = Color.Green;
TestChart.Series["AXJO"].ChartType = SeriesChartType.Line;
TestChart.Series["AXJO"].Points.DataBindXY(Xseries, AXJO);
TestChart.Series["AXJO"].ChartArea = "TestChartArea";
}
if (TestChart.Series.IsUniqueName("ES"))
{
TestChart.Series.Add("ES");
TestChart.Series["ES"].YAxisType = AxisType.Primary;
TestChart.Series["ES"].Color = Color.Red;
TestChart.Series["ES"].ChartType = SeriesChartType.Line;
TestChart.Series["ES"].Points.DataBindXY(Xseries, ES);
TestChart.Series["ES"].ChartArea = "TestChartArea";
}
if (TestChart.Series.IsUniqueName("Diff"))
{
TestChart.Series.Add("Diff");
TestChart.Series["Diff"].YAxisType = AxisType.Secondary;
TestChart.Series["Diff"].Color = Color.Blue;
TestChart.Series["Diff"].ChartType = SeriesChartType.Line;
TestChart.Series["Diff"].Points.DataBindXY(Xseries, Diff);
TestChart.Series["Diff"].ChartArea = "TestChartArea";
}
}
public void AddStripLine()
{
// add stripline at Diff=zero
StripLine ZeroDiff = new StripLine();
ZeroDiff.ForeColor = Color.Black;
ZeroDiff.BackColor = Color.Black;
ZeroDiff.StripWidth = 1;
ZeroDiff.BorderWidth = 2;
ZeroDiff.Interval = 0;
ZeroDiff.IntervalOffset = 10;
TestChart.ChartAreas["TestChartArea"].AxisY2.StripLines.Add(ZeroDiff);
}
private void button1_Click(object sender, EventArgs e)
{
PlotChart();
AddStripLine();
}
}
You asked about the unwanted placement of the AxisY2 by setting its Crossing property to 0
Simply not setting it, thus leaving it at the default double.NaN for automatically placing it at the right will resolve the issue..:
Crossing = double.NaN
To make a stripline show, it needs to start within the visible range of its axis. Offsetting it by 10 is way overboard for your data.. Also making it black is probably not what you want, unless you only want a thin line, not a colored area..
The basic rules for StripLines are:
When Interval = 0 only one stripline is shown at IntervalOffset with a width/height of StripWidth
When Interval > 0 many striplines are shown, going over the whole axis; unless you have a semi-tranparent color you need to make sure that StripWidth < Interval or else there is no space between them!
All measures are in axis-values; the types can be set with StripWidthType and IntervalType; useful especially when using one of the DateTime units.
To make the 0 values of both y-axes align, you need to tweak the Minimum and/or Maximum values of one or both axes. This may be a bit tricky and you will probably need to look into your data and take full control of spacing and placing the axis labels..
I'm using a FlowDocument to create a report. Now, I created a paginator in order to be able to repeat the header on every page, however, it does not get rendered on each page. I suspect the problem is that the Viewbox is not rendered/created untill you try to display it.
This is my GetPage method:
public override DocumentPage GetPage(int pageNumber) {
DocumentPage page = m_Paginator.GetPage(pageNumber);
ContainerVisual newpage = new ContainerVisual();
DrawingVisual title = new DrawingVisual();
using (DrawingContext ctx = title.RenderOpen())
{
var header = getHeader();
RenderTargetBitmap bmp = new RenderTargetBitmap(165, 32, 96, 96,
PixelFormats.Pbgra32);
bmp.Render(header);
ctx.DrawImage(bmp,new Rect(new Point(0,0),new Size(166, 33)));
}
ContainerVisual smallerPage = new ContainerVisual();
title.Children.Add(getHeader());
newpage.Children.Add(title);
smallerPage.Children.Add(page.Visual);
smallerPage.Transform = new MatrixTransform(0.95, 0, 0, 0.95, 0.025 * page.ContentBox.Width, 0.025 * page.ContentBox.Height);
newpage.Children.Add(smallerPage);
newpage.Transform = new TranslateTransform(m_Margin.Width, m_Margin.Height);
return new DocumentPage(newpage, m_PageSize, Move(page.BleedBox), Move(page.ContentBox));
}
Here's the Move method:
Rect Move(Rect rect) {
if (rect.IsEmpty) {
return rect;
}
else {
return new Rect(rect.Left + m_Margin.Width, rect.Top + m_Margin.Height,
rect.Width, rect.Height);
}
}
And here is getHeader() (Yes, I know, it should be GetHeader() - them conventions)
private Viewbox getHeader() {
Grid gr = new Grid();
var sr = Application.GetResourceStream(new Uri("Propuestas;component/img/log.xaml", UriKind.Relative));
var img = (Canvas)XamlReader.Load(new XmlTextReader(sr.Stream));
var logo = new Viewbox {
Child = img,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
Width = 165
};
var detalles = new TextBlock {
FontSize = 10,
FontFamily = new FontFamily("Verdana"),
Padding = new Thickness(logo.Width + 15, 0, 0, 0)
};
App.Comando.CommandText = "SELECT RazEmp, DirEmp, CpEmp, PobEmp, ProEmp, TelEmp, CifEmp FROM META4.Empresa";
using (var reader = App.Comando.ExecuteReader())
while (reader.Read())
detalles.Text = "" + reader.GetString(0).Trim() + "\n" + reader.GetString(1).Trim() + "\n" +
reader.GetDecimal(2) + " - " + reader.GetString(3).Trim() + "(" +
reader.GetString(4).Trim() + ")\n" + "Tlf: " + reader.GetString(5).Trim() +
"\nCIF: " + reader.GetString(6).Trim();
var pd = new TextBox {
Text = "PEDIDO DE COMPRA",
TextAlignment = TextAlignment.Left,
FontSize = 19,
FontFamily = new FontFamily("Verdana"),
FontWeight = FontWeights.Bold,
Background = new SolidColorBrush(Color.FromRgb(192, 192, 192)),
Margin = new Thickness(logo.Width + 15, 10, 0, 20),
BorderThickness = new Thickness(0)
};
gr.ColumnDefinitions.Add(new ColumnDefinition());
gr.ColumnDefinitions.Add(new ColumnDefinition());
gr.RowDefinitions.Add(new RowDefinition());
gr.RowDefinitions.Add(new RowDefinition());
Grid.SetRow(logo, 0);
Grid.SetRow(detalles, 0);
Grid.SetRow(pd, 1);
Grid.SetColumn(pd, 0);
Grid.SetColumnSpan(pd, 2);
Grid.SetColumnSpan(detalles, 2);
gr.Children.Add(logo);
gr.Children.Add(detalles);
gr.Children.Add(pd);
Viewbox vb = new Viewbox();
vb.Child = gr;
return vb;
}
However, when I hit print, it prints it normally, without repeating the header. I can see the query running up in debug, so addHeader() gets executed. The width and height are predetermined and fixed. Both header.Width/header.Height and header.ActualWidth/header.ActualHeight give me either 0 or NaN, which makes me believe that the viewbox isn't rendered in the background. Is there any way I would be able to repeat this on each page?
The problem is that my header contains one image and two parts text. I already had it created to be put on the first page only, but now the requirements have changed and I have to repeat it on every page.
Any help is greatly appreciated.
Later Edit: Also tried this, didn't work either.
private static BitmapSource CaptureScreen(Visual target, double dpiX, double dpiY) {
if (target == null)
return null;
Size size = new Size(165, 31.536);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)(size.Width * dpiX / 96.0),
(int)(size.Height * dpiY / 96.0),
dpiX,
dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen()) {
VisualBrush vb = new VisualBrush(target);
ctx.DrawRectangle(vb, null, new Rect(new Point(), size));
}
rtb.Render(dv);
return rtb;
}
Fixed by adding
vb.Measure(new System.Windows.Size(headerWidth, headerHeight));
vb.Arrange(new Rect(15,15,headerWidth,headerHeight));
vb.UpdateLayout();
to the getHeader method. Now it looks like this:
private Viewbox getHeader() {
Grid gr = new Grid();
var sr = Application.GetResourceStream(new Uri("Propuestas;component/img/log.xaml", UriKind.Relative));
var img = (Canvas)XamlReader.Load(new XmlTextReader(sr.Stream));
var logo = new Viewbox {
Child = img,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
Width = 165
};
var detalles = new TextBlock {
FontSize = 10,
FontFamily = new FontFamily("Verdana"),
Padding = new Thickness(logo.Width + 15, 0, 0, 0)
};
App.Comando.CommandText = "SELECT RazEmp, DirEmp, CpEmp, PobEmp, ProEmp, TelEmp, CifEmp FROM META4.Empresa";
using (var reader = App.Comando.ExecuteReader())
while (reader.Read())
detalles.Text = "" + reader.GetString(0).Trim() + "\n" + reader.GetString(1).Trim() + "\n" +
reader.GetDecimal(2) + " - " + reader.GetString(3).Trim() + "(" +
reader.GetString(4).Trim() + ")\n" + "Tlf: " + reader.GetString(5).Trim() +
"\nCIF: " + reader.GetString(6).Trim();
var pd = new TextBox {
Text = "PEDIDO DE COMPRA " + numPCO,
TextAlignment = TextAlignment.Left,
FontSize = 19,
FontFamily = new FontFamily("Verdana"),
FontWeight = FontWeights.Bold,
Background = new SolidColorBrush(Color.FromRgb(192, 192, 192)),
Margin = new Thickness(logo.Width + 15, 10, 0, 20),
BorderThickness = new Thickness(0)
};
gr.ColumnDefinitions.Add(new ColumnDefinition());
gr.ColumnDefinitions.Add(new ColumnDefinition());
gr.RowDefinitions.Add(new RowDefinition());
gr.RowDefinitions.Add(new RowDefinition());
Grid.SetRow(logo, 0);
Grid.SetRow(detalles, 0);
Grid.SetRow(pd, 1);
Grid.SetColumn(pd, 0);
Grid.SetColumnSpan(pd, 2);
Grid.SetColumnSpan(detalles, 2);
gr.Children.Add(logo);
gr.Children.Add(detalles);
gr.Children.Add(pd);
Viewbox vb = new Viewbox();
vb.Child = gr;
vb.Measure(new System.Windows.Size(headerWidth, headerHeight));
vb.Arrange(new Rect(15,15,headerWidth,headerHeight));
vb.UpdateLayout();
return vb;
}
I want to draw a signal image as shown below at runtime on canvas.
sample code which I used to draw this signal is as below.
Ellipse Ellipse1 = new Ellipse();
Ellipse Ellipse2 = new Ellipse();
Ellipse Ellipse3 = new Ellipse();
Line lineV = new Line();
Line lineH = new Line();
lineV.Stroke = SystemColors.WindowFrameBrush;
lineV.X1 = EndPosition.X;
lineV.Y1 = EndPosition.Y;
lineV.X2 = StartPosition.X;
lineV.Y2 = EndPosition.Y;
SolidColorBrush redBrush = new SolidColorBrush();
redBrush.Color = Colors.Black;
lineV.StrokeThickness = 2;
lineV.Stroke = redBrush;
canvas1.Children.Add(lineV);
lineH.Stroke = SystemColors.WindowFrameBrush;
lineH.X1 = StartPosition.X;
lineH.Y1 = EndPosition.Y;
lineH.X2 = StartPosition.X;
lineH.Y2 = StartPosition.Y;
redBrush.Color = Colors.Black;
lineH.StrokeThickness = 2;
lineH.Stroke = redBrush;
canvas1.Children.Add(lineH);
SolidColorBrush mySolidColorBrush1 = new SolidColorBrush();
mySolidColorBrush1.Color = Colors.Red; //FromArgb(255, 255, 255, 0);
Ellipse1.Fill = mySolidColorBrush1;
Ellipse1.StrokeThickness = 2;
Ellipse1.Stroke = Brushes.Black;
Ellipse1.Width = 30;
Ellipse1.Height = 30;
Ellipse1.Margin = new Thickness(EndPosition.X, EndPosition.Y - 15, EndPosition.X + 50, EndPosition.Y + 50);
canvas1.Children.Add(Ellipse1);
SolidColorBrush mySolidColorBrush2 = new SolidColorBrush();
mySolidColorBrush2.Color = Colors.Green; //FromArgb(255, 255, 255, 0);
Ellipse2.Fill = mySolidColorBrush2;
Ellipse2.StrokeThickness = 2;
Ellipse2.Stroke = Brushes.Black;
Ellipse2.Width = 30;
Ellipse2.Height = 30;
Ellipse2.Margin = new Thickness(EndPosition.X + 30, EndPosition.Y - 15, EndPosition.X + 60, EndPosition.Y + 50);
canvas1.Children.Add(Ellipse2);
SolidColorBrush mySolidColorBrush3 = new SolidColorBrush();
mySolidColorBrush3.Color = Colors.Yellow; // FromArgb(255, 255, 255, 0);
Ellipse3.Fill = mySolidColorBrush3;
Ellipse3.StrokeThickness = 2;
Ellipse3.Stroke = Brushes.Black;
Ellipse3.Width = 30;
Ellipse3.Height = 30;
Ellipse3.Margin = new Thickness(EndPosition.X + 60, EndPosition.Y - 15, EndPosition.X + 150, EndPosition.Y + 50);
canvas1.Children.Add(Ellipse3);
**Now I want the user to be able to interactively move this signal on the canvas on mouse move events.
How can I able to do this ?**
Iam using C# WPF.
If want to implement a canvas to drag elements, a DragCanvas is your choice.
Dragging Elements in a Canvas from Josh Smith and after Dragging Elements in a Canvas from igkutikov that adapt Josh Smith code. There are articles with #mustread category.
With the dragCanvas you can implement a full functionality Dragging Element Canvas, and better adapt to your code. Happy coding!