draw vertical line with D3 ( Dynamic Data Display) - dynamic-data-display

I am creating a ChartPlotter and using CursorCoordinateGraph i am able to get the X coordinate on MouseLeftButtonDown event.
private CursorCoordinateGraph mouseTrack;
private void OnLoaded(object sender, RoutedEventArgs e)
{
mouseTrack = new CursorCoordinateGraph();
firstPlotter.Children.Add(mouseTrack);
}
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point mousePos = mouseTrack.Position;
var transform = firstPlotter.Viewport.Transform;
Point mousePosInData = mousePos.ScreenToData(transform);
double xValue = mousePosInData.X;
}
Is there a way to draw a vertical line on that xValue coordinate? I am a bit lost in line graphs, lines, vertical lines..

Add this lines of code after the computation of xValue in OnMouseLeftButtonDown.
VerticalLine vl = new VerticalLine();
vl.Value = xValue;
I assume you want to add that line to the aforementioned plottter:
firstPlotter.Children.Add(vl);
You can use the same approach for HorizontalLine.

Related

pass a variable to the result of an asynchronous call method's

There is a DataGrid with data in the Net 4.0 App. For the selected row, I get the value of one of the columns and pass it to the asynchronous method of the WCF service. Is it possible to pass this value as a result this method?
btn_Click(object sender, RoutedEventArgs e) {
DataRowView rv = (DataRowView)dgData.SelectedItem;
rv["TimeBeg"] = DateTime.Now.ToString("h:mm:ss");
string val=rv["Id"].ToString();
srAsync.ServClient clP = new srAsync.ServClient();
clP.MethodCompleted += cl_MethodComplete;
clP.MethodAsync(val);
}
After the call, the user can select another DataGrid Item, and call Async method for them, but in complete method I need to call another method with this value and update the rows DataGrid
private void cl_MethodComplete(object sender, srA.MethodCompletedEventArgs e) {
rv["TimeEnd"] = DateTime.Now.ToString("h:mm:ss");
sr.ServClient clP = new sr.ServClient();
clP.AnotherMethod(val);
...
What I would do is passing the row the user clicks on to the handler, using a lambda function:
btn_Click(object sender, RoutedEventArgs e) {
DataRowView rv = (DataRowView)dgData.SelectedItem;
rv["TimeBeg"] = DateTime.Now.ToString("h:mm:ss");
string val = rv["Id"].ToString();
srAsync.ServClient clP = new srAsync.ServClient();
clP.MethodCompleted += (currentSender, currentE) => cl_MethodComplete(currentSender, currentE, rv);
clP.MethodAsync(val);
}
Of course you will have to add another parameter to cl_MethodComplete, which will be able to work on the original row:
private void cl_MethodComplete(object sender, srA.MethodCompletedEventArgs e, DataRowView originalRow) {
originalRow["TimeEnd"] = DateTime.Now.ToString("h:mm:ss");
sr.ServClient clP = new sr.ServClient();
clP.AnotherMethod(val);
...

Windows Phone 8.1 RT: how to prevent manipulation event throw object?

I'm new C# beginer. I want to prevent throwing XAML's object by manipulation event. My app is developed in Windows Phone 8.1 RT.
I have XAML's REctangle:
<Canvas x:Name="MyCanvas" Background="White">
<Rectangle Name="TestRectangle"
Width="100" Height="200" Fill="Blue"
ManipulationMode="All"/>
</Canvas>
In MainPage:
public MainPage()
{
this.InitializeComponent();
// Handle manipulation events.
TestRectangle.ManipulationDelta += Drag_ManipulationDelta;
dragTranslation = new TranslateTransform();
TestRectangle.RenderTransform = this.dragTranslation;
this.NavigationCacheMode = NavigationCacheMode.Required;
}
void Drag_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
// Move the rectangle.
dragTranslation.X += e.Delta.Translation.X;
dragTranslation.Y += e.Delta.Translation.Y;
}
private void TestRectangle_PointerPressed(object sender,
PointerRoutedEventArgs e)
{
Rectangle rect = sender as Rectangle;
// Change the size of the Rectangle
if (null != rect)
{
rect.Width = 250;
rect.Height = 150;
}
}
private void TestRectangle_PointerReleased(object sender,
PointerRoutedEventArgs e)
{
Rectangle rect = sender as Rectangle;
// Reset the dimensions on the Rectangle
if (null != rect)
{
rect.Width = 200;
rect.Height = 100;
}
}
private void TestRectangle_PointerExited(object sender,
PointerRoutedEventArgs e)
{
Rectangle rect = sender as Rectangle;
// Finger moved out of Rectangle before the pointer exited event
// Reset the dimensions on the Rectangle
if (null != rect)
{
rect.Width = 200;
rect.Height = 100;
}
}
How to move object whitout throwing when user exit event ?
I'm assuming that by 'throwing' you mean you want to remove the inertial aspect of your rectangle? In that case remove the ManipulationMode setter from your XAML code and insert this line in your page's constructor (C#):
TestRectangle.ManipulationMode = ManipulationMode.TranslateX | ManipulationMode.TranslateY;
That should remove the intertial effect you're talking about. As a side note though, this method of moving UIElements will give you a pretty annoying lag. I faced a similar problem a little while ago and the issue was resolved by using a different approach:
Delay in drag/drop of UIElement in Windows Phone 8.1

Trying to get HorizontalOffset, always returns 0

I am writing an app with C#/xaml for Windows8 Metro.
I have a Scrollviewer and would like to get the horizontaloffset.
I tryed it with this:
private void ScrollViewer_ViewChanged_1(object sender, ScrollViewerViewChangedEventArgs e)
{
int i = Convert.ToInt32(GetValue(ScrollViewer.HorizontalOffsetProperty));
}
but i is always 0, althrough in the debugger it shows me an offset of 221.09 and i scrolled down!
Michael
If you scrolled down - your horizontal offset wouldn't change unless you scrolled horizontally.
Perhaps your event handler isn't on the ScrollViewer itself and if that's the case - you would need to call GetValue on the SV itself, e.g.
private void ScrollViewer_ViewChanged_1(object sender, ScrollViewerViewChangedEventArgs e)
{
int i = Convert.ToInt32(myScrollViewer.GetValue(ScrollViewer.HorizontalOffsetProperty));
}
or better yet just do this:
private void ScrollViewer_ViewChanged_1(object sender, ScrollViewerViewChangedEventArgs e)
{
int i = Convert.ToInt32(myScrollViewer.HorizontalOffset);
}

Resizing a label and Font of the form based on the window sizing

I'm looking for help resizing a label's size and its font size based on its window size.
That's to say when a window resizes, the label itself adjusts it font and background box to do the same.
I know I'm triggering something on the Resize event of the form, but I don't know what. Can anyone help?
This is in C# but it might help you.
public Form1()
{
InitializeComponent();
this.Resize += new EventHandler(Form1_Resize);
label1.AutoSize = false;
label1.Size = new Size(100, 50);
label1.BackColor = Color.White;
}
void Form1_Resize(object sender, EventArgs e)
{
label1.Size = new Size(this.ClientSize.Width / 3, this.ClientSize.Height / 3);
label1.Font = new Font("Arial", this.ClientSize.Height / 20);
}
A label is set to AutoSize by default, which should take care of itself (assuming that's what you mean by 'background box').
So, all you need to do is change the font based on the new size of the form. This should do it:
private int _lastFormSize;
private void Form1_Resize(object sender, EventArgs e)
{
var bigger = GetArea(this.Size) > _lastFormSize;
float scaleFactor = bigger ? 1.1f : 0.9f;
label1.Font = new Font(label1.Font.FontFamily.Name, label1.Font.Size*scaleFactor);
_lastFormSize = GetArea(this.Size);
}
private int GetArea(Size size)
{
return size.Height*size.Width;
}
You would probably want to deterministically calculate the scale factor based on how much the area of the form has increased/decreased by, but that code should at least get you the effect.

How to make a custom ComboBox (OwnerDrawFixed) looks 3D like the standard ComboBox?

I am making a custom ComboBox, inherited from Winforms' standard ComboBox. For my custom ComboBox, I set DrawMode to OwnerDrawFixed and DropDownStyle to DropDownList. Then I write my own OnDrawItem method. But I ended up like this:
How do I make my Custom ComboBox to look like the Standard one?
Update 1: ButtonRenderer
After searching all around, I found the ButtonRenderer class. It provides a DrawButton static/shared method which -- as the name implies -- draws the proper 3D button. I'm experimenting with it now.
Update 2: What overwrites my control?
I tried using the Graphics properties of various objects I can think of, but I always fail. Finally, I tried the Graphics of the form, and apparently something is overwriting my button.
Here's the code:
Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
Dim TextToDraw As String = _DefaultText
__Brush_Window.Color = Color.FromKnownColor(KnownColor.Window)
__Brush_Disabled.Color = Color.FromKnownColor(KnownColor.GrayText)
__Brush_Enabled.Color = Color.FromKnownColor(KnownColor.WindowText)
If e.Index >= 0 Then
TextToDraw = _DataSource.ItemText(e.Index)
End If
If TextToDraw.StartsWith("---") Then TextToDraw = StrDup(3, ChrW(&H2500)) ' U+2500 is "Box Drawing Light Horizontal"
If (e.State And DrawItemState.ComboBoxEdit) > 0 Then
'ButtonRenderer.DrawButton(e.Graphics, e.Bounds, VisualStyles.PushButtonState.Default)
Else
e.DrawBackground()
End If
With e
If _IsEnabled(.Index) Then
.Graphics.DrawString(TextToDraw, Me.Font, __Brush_Enabled, .Bounds.X, .Bounds.Y)
Else
'.Graphics.FillRectangle(__Brush_Window, .Bounds)
.Graphics.DrawString(TextToDraw, Me.Font, __Brush_Disabled, .Bounds.X, .Bounds.Y)
End If
End With
TextToDraw = Nothing
ButtonRenderer.DrawButton(Me.Parent.CreateGraphics, Me.ClientRectangle, VisualStyles.PushButtonState.Default)
'MyBase.OnDrawItem(e)
End Sub
And here's the result:
Replacing Me.Parent.CreateGraphics with e.Graphics got me this:
And doing the above + replacing Me.ClientRectangle with e.Bounds got me this:
Can anyone point me whose Graphics I must use for the ButtonRenderer.DrawButton method?
PS: The bluish border is due to my using PushButtonState.Default instead of PushButtonState.Normal
I Found An Answer! (see below)
I forgot where I found the answer... I'll edit this answer when I remember.
But apparently, I need to set the Systems.Windows.Forms.ControlStyles flags. Especially the ControlStyles.UserPaint flag.
So, my New() now looks like this:
Private _ButtonArea as New Rectangle
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
MyBase.SetStyle(ControlStyles.Opaque Or ControlStyles.UserPaint, True)
MyBase.DrawMode = Windows.Forms.DrawMode.OwnerDrawFixed
MyBase.DropDownStyle = ComboBoxStyle.DropDownList
' Cache the button's modified ClientRectangle (see Note)
With _ButtonArea
.X = Me.ClientRectangle.X - 1
.Y = Me.ClientRectangle.Y - 1
.Width = Me.ClientRectangle.Width + 2
.Height = Me.ClientRectangle.Height + 2
End With
End Sub
And now I can hook into the OnPaint event:
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
If Me.DroppedDown Then
ButtonRenderer.DrawButton(Me.CreateGraphics, _ButtonArea, VisualStyles.PushButtonState.Pressed)
Else
ButtonRenderer.DrawButton(Me.CreateGraphics, _ButtonArea, VisualStyles.PushButtonState.Normal)
End If
MyBase.OnPaint(e)
End Sub
Note: Yes, the _ButtonArea rectangle must be enlarged by 1 pixel to all directions (up, down, left, right), or else there will be a 1-pixel 'perimeter' around the ButtonRenderer that shows garbage. Made me crazy for awhile until I read that I must enlarge the Control's rect for ButtonRenderer.
I had this problem myself and the reply by pepoluan got me started. I still think a few things are missing in order to get a ComboBox with looks and behavior similar to the standard ComboBox with DropDownStyle=DropDownList though.
DropDownArrow
We also need to draw the DropDownArrow. I played around with the ComboBoxRenderer, but it draws a dark border around the area of the drop down arrow so that didn't work.
My final solution was to simply draw a similar arrow and render it onto the button in the OnPaint method.
Hot Item Behavior
We also need to ensure our ComboBox has a hot item behavior similar to the standard ComboBox. I don't know of any simple and reliable method to know when a mouse is no longer above the control. Therefore I suggest using a Timer that checks at each tick whether the mouse is still over the control.
Edit
Just added a KeyUp event handler to make sure the control would update correctly when a selection was made using the keyboard. Also made a minor correction of where the text was rendered, to ensure it is more similar to the vanilla combobox' text positioning.
Below is the full code of my customized ComboBox. It allows you to display images on each item and is always rendered as in the DropDownList style, but hopefully it should be easy to accommodate the code to your own solution.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
namespace CustomControls
{
/// <summary>
/// This is a special ComboBox that each item may conatins an image.
/// </summary>
public class ImageComboBox : ComboBox
{
private static readonly Size arrowSize = new Size(18, 20);
private bool itemIsHot;
/* Since properties such as SelectedIndex and SelectedItems may change when the mouser is hovering over items in the drop down list
* we need a property that will store the item that has been selected by comitted selection so we know what to draw as the selected item.*/
private object comittedSelection;
private readonly ImgHolder dropDownArrow = ImgHolder.Create(ImageComboBox.DropDownArrow());
private Timer hotItemTimer;
public Font SelectedItemFont { get; set; }
public Padding ImageMargin { get; set; }
//
// Summary:
// Gets or sets the path of the property to use as the image for the items
// in the System.Windows.Forms.ListControl.
//
// Returns:
// A System.String representing a single property name of the System.Windows.Forms.ListControl.DataSource
// property value, or a hierarchy of period-delimited property names that resolves
// to a property name of the final data-bound object. The default is an empty string
// ("").
//
// Exceptions:
// T:System.ArgumentException:
// The specified property path cannot be resolved through the object specified by
// the System.Windows.Forms.ListControl.DataSource property.
[DefaultValue("")]
[Editor("System.Windows.Forms.Design.DataMemberFieldEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
public string ImageMember { get; set; }
public ImageComboBox()
{
base.SetStyle(ControlStyles.Opaque | ControlStyles.UserPaint, true);
//All the elements in the control are drawn manually.
base.DrawMode = DrawMode.OwnerDrawFixed;
//Specifies that the list is displayed by clicking the down arrow and that the text portion is not editable.
//This means that the user cannot enter a new value.
//Only values already in the list can be selected.
this.DropDownStyle = ComboBoxStyle.DropDownList;
//using DrawItem event we need to draw item
this.DrawItem += this.ComboBoxDrawItemEvent;
this.hotItemTimer = new Timer();
this.hotItemTimer.Interval = 250;
this.hotItemTimer.Tick += this.HotItemTimer_Tick;
this.MouseEnter += this.ImageComboBox_MouseEnter;
this.KeyUp += this.ImageComboBox_KeyUp;
this.SelectedItemFont = this.Font;
this.ImageMargin = new Padding(4, 4, 5, 4);
this.SelectionChangeCommitted += this.ImageComboBox_SelectionChangeCommitted;
this.SelectedIndexChanged += this.ImageComboBox_SelectedIndexChanged;
}
private static Image DropDownArrow()
{
var arrow = new Bitmap(8, 4, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(arrow))
{
g.CompositingQuality = CompositingQuality.HighQuality;
g.FillPolygon(Brushes.Black, ImageComboBox.CreateArrowHeadPoints());
}
return arrow;
}
private static PointF[] CreateArrowHeadPoints()
{
return new PointF[4] { new PointF(0, 0), new PointF(7F, 0), new PointF(3.5F, 3.5F), new PointF(0, 0) };
}
private static void DrawComboBoxItem(Graphics g, string text, Image image, Rectangle itemArea, int itemHeight, int itemWidth, Padding imageMargin
, Brush brush, Font font)
{
if (image != null)
{
// recalculate margins so image is always approximately vertically centered
int extraImageMargin = itemHeight - image.Height;
int imageMarginTop = Math.Max(imageMargin.Top, extraImageMargin / 2);
int imageMarginBotttom = Math.Max(imageMargin.Bottom, extraImageMargin / 2);
g.DrawImage(image, itemArea.X + imageMargin.Left, itemArea.Y + imageMarginTop, itemHeight, itemHeight - (imageMarginBotttom
+ imageMarginTop));
}
const double TEXT_MARGIN_TOP_PROPORTION = 1.1;
const double TEXT_MARGIN_BOTTOM_PROPORTION = 2 - TEXT_MARGIN_TOP_PROPORTION;
int textMarginTop = (int)Math.Round((TEXT_MARGIN_TOP_PROPORTION * itemHeight - g.MeasureString(text, font).Height) / 2.0, 0);
int textMarginBottom = (int)Math.Round((TEXT_MARGIN_BOTTOM_PROPORTION * itemHeight - g.MeasureString(text, font).Height) / 2.0, 0);
//we need to draw the item as string because we made drawmode to ownervariable
g.DrawString(text, font, brush, new RectangleF(itemArea.X + itemHeight + imageMargin.Left + imageMargin.Right, itemArea.Y + textMarginTop
, itemWidth, itemHeight - textMarginBottom));
}
private string GetDistplayText(object item)
{
if (this.DisplayMember == string.Empty) { return item.ToString(); }
else
{
var display = item.GetType().GetProperty(this.DisplayMember).GetValue(item).ToString();
return display ?? item.ToString();
}
}
private Image GetImage(object item)
{
if (this.ImageMember == string.Empty) { return null; }
else { return item.GetType().GetProperty(this.ImageMember).GetValue(item) as Image; }
}
private void ImageComboBox_SelectionChangeCommitted(object sender, EventArgs e)
{
this.comittedSelection = this.Items[this.SelectedIndex];
}
private void HotItemTimer_Tick(object sender, EventArgs e)
{
if (!this.RectangleToScreen(this.ClientRectangle).Contains(Cursor.Position)) { this.TurnOffHotItem(); }
}
private void ImageComboBox_KeyUp(object sender, KeyEventArgs e)
{
this.Invalidate();
}
private void ImageComboBox_MouseEnter(object sender, EventArgs e)
{
this.TurnOnHotItem();
}
private void ImageComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (!this.DroppedDown)
{
if (this.SelectedIndex > -1) { this.comittedSelection = this.Items[this.SelectedIndex]; }
else { this.comittedSelection = null; }
}
}
private void TurnOnHotItem()
{
this.itemIsHot = true;
this.hotItemTimer.Enabled = true;
}
private void TurnOffHotItem()
{
this.itemIsHot = false;
this.hotItemTimer.Enabled = false;
this.Invalidate(this.ClientRectangle);
}
/// <summary>
/// Draws overridden items.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ComboBoxDrawItemEvent(object sender, DrawItemEventArgs e)
{
//Draw backgroud of the item
e.DrawBackground();
if (e.Index != -1)
{
Brush brush;
if (e.State.HasFlag(DrawItemState.Focus) || e.State.HasFlag(DrawItemState.Selected)) { brush = Brushes.White; }
else { brush = Brushes.Black; }
object item = this.Items[e.Index];
ImageComboBox.DrawComboBoxItem(e.Graphics, this.GetDistplayText(item), this.GetImage(item), e.Bounds, this.ItemHeight, this.DropDownWidth
, new Padding(0, 1, 5, 1), brush, this.Font);
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// define the area of the control where we will write the text
var topTextRectangle = new Rectangle(e.ClipRectangle.X - 1, e.ClipRectangle.Y - 1, e.ClipRectangle.Width + 2, e.ClipRectangle.Height + 2);
using (var controlImage = new Bitmap(e.ClipRectangle.Width, e.ClipRectangle.Height, PixelFormat.Format32bppArgb))
{
using (Graphics ctrlG = Graphics.FromImage(controlImage))
{
/* Render the control. We use ButtonRenderer and not ComboBoxRenderer because we want the control to appear with the DropDownList style. */
if (this.DroppedDown) { ButtonRenderer.DrawButton(ctrlG, topTextRectangle, PushButtonState.Pressed); }
else if (this.itemIsHot) { ButtonRenderer.DrawButton(ctrlG, topTextRectangle, PushButtonState.Hot); }
else { ButtonRenderer.DrawButton(ctrlG, topTextRectangle, PushButtonState.Normal); }
// Draw item, if any has been selected
if (this.comittedSelection != null)
{
ImageComboBox.DrawComboBoxItem(ctrlG, this.GetDistplayText(this.comittedSelection), this.GetImage(this.comittedSelection)
, topTextRectangle, this.Height, this.Width - ImageComboBox.arrowSize.Width, this.ImageMargin, Brushes.Black, this.SelectedItemFont);
}
/* Now we need to draw the arrow. If we use ComboBoxRenderer for this job, it will display a distinct border around the dropDownArrow and we don't want that. As an alternative we define the area where the arrow should be drawn, and then procede to draw it. */
var dropDownButtonArea = new RectangleF(topTextRectangle.X + topTextRectangle.Width - (ImageComboBox.arrowSize.Width
+ this.dropDownArrow.Image.Width) / 2.0F, topTextRectangle.Y + topTextRectangle.Height - (topTextRectangle.Height
+ this.dropDownArrow.Image.Height) / 2.0F, this.dropDownArrow.Image.Width, this.dropDownArrow.Image.Height);
ctrlG.DrawImage(this.dropDownArrow.Image, dropDownButtonArea);
}
if (this.Enabled) { e.Graphics.DrawImage(controlImage, 0, 0); }
else { ControlPaint.DrawImageDisabled(e.Graphics, controlImage, 0, 0, Color.Transparent); }
}
}
}
internal struct ImgHolder
{
internal Image Image
{
get
{
return this._image ?? new Bitmap(1, 1); ;
}
}
private Image _image;
internal ImgHolder(Bitmap data)
{
_image = data;
}
internal ImgHolder(Image data)
{
_image = data;
}
internal static ImgHolder Create(Image data)
{
return new ImgHolder(data);
}
internal static ImgHolder Create(Bitmap data)
{
return new ImgHolder(data);
}
}
}