I have added a margin (For adding breakpoints) to the left side of my TextEditor in the following manner:
public partial class LogicSimViewCodeWPFCtrl : UserControl
{
private class BreakPointMargin : AbstractMargin
{
private const int margin = 20;
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
return new PointHitTestResult(this, hitTestParameters.HitPoint);
}
protected override Size MeasureOverride(Size availableSize)
{
return new Size(margin, 0);
}
}
}
private void LogicCodeInit()
{
try
{
TxtEditCodeViewer.TextArea.LeftMargins.Insert(0, new BreakPointMargin());
...
The margin is added successfully but now I'd like to color the background of the margin. How can I accomplish this?
https://web.archive.org/web/20190716171503/http://community.sharpdevelop.net/forums/t/16047.aspx
You would have to override OnRender:
protected override void OnRender(DrawingContext drawingContext)
{
Size renderSize = this.RenderSize;
drawingContext.DrawRectangle(SystemColors.ControlBrush, null,
new Rect(0, 0, renderSize.Width, renderSize.Height));
Also, you aren't required to derived from AbstractMargin - you can use any WPF control you want. AbstractMargin just provides the TextView and Document properties and keeps them up to date. If you don't need those or can implement them yourself, you can just use another base class.
Related
My English skill is poor because I'm not a native speaker.
I have written an editor that has a visual effect like Highlight.
The editor has DrawingControl for representing a visual effect as the following code.
public class HighlightTextBox : TextBox
{
private DrawingControl renderCanvas;
}
public class DrawingControl : FrameworkElement
{
private VisualCollection visuals;
private DrawingVisual visual;
public DrawingControl()
{
visual = new DrawingVisual();
visuals = new VisualCollection(this);
visuals.Add(visual);
}
public DrawingContext GetContext()
{
return visual.RenderOpen();
}
protected override int VisualChildrenCount
{
get { return visuals.Count; }
}
protected override Visual GetVisualChild(int index)
{
if (index < 0 || index >= visuals.Count)
throw new ArgumentOutOfRangeException();
return visuals[index];
}
}
If a user input a character on the editor then the TextChanged event is called.
And after that, the OnRender function is called by calling InvalidateVisual function.
TextChanged(s,e)
{
InvalidateVisual();
}
Then all text is drawn that has a visual effect by using DrawingContext in the DrawingControl.
protected override void OnRender(DrawingContext drawingContext)
{
if (this.bSingleLineChanged)
{
this.SingleLineChangedRender(drawingContext);
this.bSingleLineChanged = false;
return;
}
else
this.AllRender(drawingContext);
}
private void AllRender(DrawingContext drawingContext)
{
// Calculate drawing position, texts, etc...
var dc = this.renderCanvas.GetContext();
// Here draw texts
dc.Close();
base.OnRender(drawingContext);
}
As a result, drawing process success when all text is repainted but the way take a lot of time.
To shorten a drawing time, I tried to repaint only an updated part.
The part drawing process is defined in the SingleLineChangedRender function.
Also the logic of the function alike with an AllRender function.
Now I would explain a problem.
I calculate an updated part and have written logic in the SingleLineChangedRender function.
But when is called a GetContext function in the SingleLineChangedRender function all drawn context is erased.
private void SingleLineChangedRender(DrawingContext drawingContext)
{
// I think that here all drawn contexts are erased.
var dc = this.renderCanvas.GetContext();
// Here draw texts
dc.Close();
base.OnRender(drawingContext);
}
I want to repaint only an updated part but I can't do it because all contexts is erased when the GetContext function is called.
I would like to seek your advice to solve this problem.
Thank you for reading.
I follow your advice and I solved this problem by updating DrawingControl class.
I updated the TextViewer class as a container of DrawingContext.
As a result, the class has formed the following.
public class TextViewer : FrameworkElement
{
// For highlighting of the selected line.
private DrawingVisual selectionLineAppearance = new DrawingVisual();
// For highlighting tokens of the lines.
private VisualCollection lines;
protected override int VisualChildrenCount
{
// selectionLineAppearance + lines
get { return 1+lines.Count; }
}
protected override Visual GetVisualChild(int index)
{
if (index < 0 || index >= VisualChildrenCount)
throw new ArgumentOutOfRangeException();
if (index == 0) return this.selectionLineAppearance;
return lines[index-1];
}
// logices
...
}
Now, Editor can repaint only an updated part. Addition can paint the appearance of the selected line.
Thank you for your advice.
You can make custom panels in UWP XAML by deriving from the Panel class and overriding MeasureOverride and ArrangeOverride. How would I go about doing the same thing for a panel with just one child, similar to the Border control? Unfortunately, I cannot derive from Border because it's sealed.
I tried this but it doesn't work (of course, this is a simplified sample for what I'm trying to achieve):
public sealed class ProportionedPresenter : FrameworkElement
{
public static readonly DependencyProperty ChildProperty = DependencyProperty.Register(
"Child",
typeof(object),
typeof(ProportionedPresenter),
new PropertyMetadata(null));
public object Child
{
get { return this.GetValue(ProportionedPresenter.ChildProperty); }
set { this.SetValue(ProportionedPresenter.ChildProperty, value); }
}
protected override Size MeasureOverride(Size availableSize)
{
var minDimension = Math.Min(availableSize.Width, availableSize.Height);
var desiredSize = new Size(minDimension, minDimension);
if (this.Child is UIElement childElement)
{
childElement.Measure(desiredSize);
var maxDimension = Math.Max(childElement.DesiredSize.Width, childElement.DesiredSize.Height);
desiredSize = new Size(maxDimension, maxDimension);
}
return desiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
if (this.Child is UIElement childElement)
{
childElement.Arrange(new Rect(new Point(), childElement.DesiredSize));
}
return finalSize;
}
}
I want to add the default iOS footer to the tablesection in the tableview in Xamarin Forms. How can I go about doing this? I assume a customer renderer but I'm only reading that this can be done for Tableview?
To show an example, the following image is from Xcode storyboards when I enter the footer text on a static cell.
A Custom renderer is right, but you will have to use a custom renderer for the entire TableView. From there, you will need to override the TableViewModelRenderer and then the GetViewForFooter method in that ModelRenderer. Here's something that might help get you started:
public class FooterTableViewRenderer : TableViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
{
base.OnElementChanged(e);
if (Control == null)
return;
var tableView = Control as UITableView;
var formsTableView = Element as TableView;
tableView.WeakDelegate = new CustomFooterTableViewModelRenderer (formsTableView);
}
private class CustomFooterTableViewModelRenderer : TableViewModelRenderer
{
public CustomFooterTableViewModelRenderer(TableView model) : base(model)
{
}
public override UIView GetViewForFooter(UITableView tableView, nint section)
{
return new UILabel()
{
Text = TitleForFooter(tableView, section), // or use some other text here
TextAlignment = UITextAlignment.Center
};
}
}
}
As mentioned in my comments below, you can alternatively override other methods in your TableViewModelRenderer:
public override nfloat GetHeightForFooter(UITableView tableView, nint section)
{
return 10;
}
public override string TitleForFooter(UITableView tableView, nint section)
{
return "This is the title for this given section";
}
I am newbie in MonoDroid. How can I draw ellipse in runtime using C# in Android Application?
To draw an ellipse, or other geometric shapes, you can use the canvas object. Here's a very basic bit of code that will draw an ellipse (oval). I basically just created a view and overrode the OnDraw method to draw the ellipse. You define a RectF object which defines the rectangular boundary of the ellipse. A good reference is the Android SDK:
http://developer.android.com/reference/android/graphics/Canvas.html
[Activity(Label = "MonoAndroidApplication1", MainLauncher = true, Icon = "#drawable/icon")]
public class Activity1 : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
var targetView = new OvalView(this);
SetContentView(targetView);
}
}
public class OvalView : View
{
public OvalView(Context context) : base(context) { }
protected override void OnDraw(Canvas canvas)
{
RectF rect = new RectF(0,0, 300, 300);
canvas.DrawOval(rect, new Paint() { Color = Color.CornflowerBlue });
}
}
I am trying to add an simple Textblock as adorment to a control. But I want it to be positionned just above my adorned control.
This is the decoration creation ( the problem doesnt rely in this code):
public void AddLabelDecoration()
{
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
TextBlock textBlockMarkTooltipContent = new TextBlock();
textBlockMarkTooltipContent.Text = "Test Label Adorner";
_labelAdornerMarkTooltipContentAdorner = new Adorner(this)
{
Child = textBlockMarkTooltipContent
};
adornerLayer.Add(_labelAdornerMarkTooltipContentAdorner);
}
What I cannot achieve to do, is the positionning of the Decoration, above the adorned control. I would like to use this MSDN code sample, which makes use of AdornerPanel so as to do the positionning...
However I have not figured out how to access to an AdornerPanel object so as to apply this MSDN code sample... neither from my adorned control, from the AdornedLayout, or the Adorner...
I admit I don't clear understand the WPF class hierarchy between AdornerPanel and AdornerLayout.
Any help appreciated.
public void AddLabelDecoration()
{
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
TextBlock textBlockMarkTooltipContent = new TextBlock();
textBlockMarkTooltipContent.Text = "Test Label Adorner";
AdornerPanel labelAdornerAdornerPanel = new AdornerPanel();
// add your TextBlock to AdornerPanel
labelAdornerAdornerPanel.Children.Add(textBlockMarkTooltipContent);
// set placements on AdornerPanel
AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.PositionRelativeToAdornerHeight(-1, 0);
placement.PositionRelativeToAdornerWidth(1, 0);
AdornerPanel.SetPlacements(labelAdornerAdornerPanel, placement);
// create Adorner with AdornerPanel inside
_labelAdornerMarkTooltipContentAdorner = new Adorner(this)
{
Child = labelAdornerAdornerPanel
};
adornerLayer.Add(_labelAdornerMarkTooltipContentAdorner);
}
In order to move your Adorner you have to override the ArrangeOverride method and adjust a new adorner position there.
Here's an example with a simple FrameworkElementAdorner.
public class FrameworkElementAdorner : Adorner
{
private FrameworkElement _child;
public FrameworkElementAdorner(UIElement adornedElement)
: base(adornedElement)
{
}
protected override int VisualChildrenCount
{
get { return 1; }
}
public FrameworkElement Child
{
get { return _child; }
set
{
if (_child != null)
{
RemoveVisualChild(_child);
}
_child = value;
if (_child != null)
{
AddVisualChild(_child);
}
}
}
protected override Visual GetVisualChild(int index)
{
if (index != 0) throw new ArgumentOutOfRangeException();
return _child;
}
protected override Size MeasureOverride(Size constraint)
{
_child.Measure(constraint);
return _child.DesiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
// Adjust your offset here:
_child.Arrange(new Rect(new Point(-20, -20), finalSize));
return new Size(_child.ActualWidth, _child.ActualHeight);
}
Usage:
TextBlock textBlockMarkTooltipContent = new TextBlock();
textBlockMarkTooltipContent.Text = "Test Label Adorner";
var adorner = new FrameworkElementAdorner(this)
{
Child = textBlockMarkTooltipContent
};