Blazor get div position / coordinates - c#

I'm creating a popup component and I want this to be movable. I can move it using the top / left style, but for now they are init to top:0;left:0; and so the popup appear on the top left corner of the page. I'm looking to make it appear on the center of the page and then get the Top Left coordinates of my div in ordor to manage properly my calcul after.
here is what I have now:
<div class="child-window" draggable="true" style="position:absolute; top: #(offsetY)px; left: #(offsetX)px; border-color: black;" #ondragend="OnDragEnd" #ondragstart="OnDragStart">
<div class="cw-content">
#Content
</div>
</div>
#code {
private double startX, startY, offsetX, offsetY;
protected override void OnInitialized() {
base.OnInitialized();
ResetStartPosition();
}
private void ResetStartPosition() {
//Set offsetX & offsetY to the top left div position
}
private void OnDragStart(DragEventArgs args) {
startX = args.ClientX;
startY = args.ClientY;
}
private void OnDragEnd(DragEventArgs args) {
offsetX += args.ClientX - startX;
offsetY += args.ClientY - startY;
}
}

At the moment it is possible with JS only
public class BoundingClientRect
{
public double X { get; set; }
public double Y { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public double Top { get; set; }
public double Right { get; set; }
public double Bottom { get; set; }
public double Left { get; set; }
}
private async Task OnElementClick(MouseEventArgs e)
{
var result = await JSRuntime.InvokeAsync<BoundingClientRect>("MyDOMGetBoundingClientRect", MyElementReference);
var x = (int) (e.ClientX - result.Left);
var y = (int) (e.ClientY - result.Top);
// now you can work with the position relative to the element.
}
and
<script> MyDOMGetBoundingClientRect = (element, parm) => { return element.getBoundingClientRect(); }; </script>

Related

I cannot set and call value using setter and getter

Learning Setter and Getter
I am making a console log app where I create a Box class and make an object and set values: width, height, and length using setter and getter. I was referencing an solution on github, but I haven't make it work yet. I don't know where I made mistake.
My Code
using System;
namespace ClassDemo2
{
class Box
{
private double _width;
private double _height;
private double _length;
public double Width
{
get { return _width; }
set { this._width = Width; }
}
public double Height
{
get { return _height; }
set { this._height = Height; }
}
public double Length
{
get { return _length; }
set {this._length = Length; }
}
public double volume()
{
return Width * Height * Length;
}
}
public class Program
{
static void Main(string[] args)
{
Box box = new Box();
//Set value
box.Width = 12;
box.Height = 12;
box.Length = 12;
//Get value
double width = box.Width;
double height = box.Height;
double length = box.Length;
Console.WriteLine("Box properties");
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Height: {0}", height);
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Volume: {0}", box.volume());
}
}
}
Console Window
The setters in the Box class aren't doing anything. The setters aren't assigning a value to the private fields in the Box class.
You may as well remove the fields altogether and use auto-implemented properties.
For example:
class Box
{
public double Width { get; set; }
public double Height { get; set; }
public double Length { get; set; }
public double Volume()
{
return Width * Height * Length;
}
}
class Box
{
public double Width { get; set; }
public double Height { get; set; }
public double Length { get; set; }
public double volume()
{
return Width * Height * Length;
}
}
Use Auto-Implemented Properties (https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties)

change child value from parent on timer elapse

I have a simple parent-child component :
parent :
<div class="container-fluid">
<div>
<ChildComponent RandomNumber="#RandomNumberX" ></ChildComponent>
</div>
</div>
#code {
public double RandomNumberX = 0.1;
private Timer timer = new Timer();
protected override void OnInitialized()
{
timer.Interval = 3000;
timer.Elapsed -= Set;
timer.Elapsed += Set;
timer.Start();
}
private void Set(object sender, ElapsedEventArgs e)
{
var rng = new Random();
var x = rng.Next(500, 600);
RandomNumberX = x;
}}
Child:
<svg height="100" width="100" style="position:absolute; border-color: black; ">
<g>
<circle cx="50%" cy="25" r="5" stroke="red" stroke-width="2" fill="red" />
<text x="50%" y="50" text-anchor="middle">#RandomNumber</text>
</g>
</svg>
#code {
[Parameter]
public double RandomNumber { get; set; }
protected override void OnParametersSet()
{
}
}
when running app "RandomNumber" show 0.1 and does not change while in parent component it changes on timer elapsed.
I animated a SVG clock a little while back that does this:
Note: The use of dispose and how I reduce the calculations to only when needed by checking for a second change.
Clock.razor
<div class="d-flex flex-column align-items-center">
<div class="time-sm">#timeZone.Id</div>
<svg width="#Size" height="#Size" viewBox="0 0 1000 1000">
<circle cx="#center" cy="#center" r="#radius" fill="#FaceColor" />
<ClockHand Angle="hourAngle" Color="#HourColor" Width="50" Length="0.9" />
<ClockHand Angle="minuteAngle" Color="#MinuteColor" Width="30" Length="0.95" />
<ClockHand Angle="secondAngle" Color="#SecondColor" Width="20" Length="1" />
</svg>
<div class="time-sm">#currentSecond.DateTime.ToShortTimeString()</div>
<div class="time-sm">#currentSecond.DateTime.ToString("dddd")</div>
</div>
Clock.razor.cs
public partial class Clock : ComponentBase, IDisposable
{
internal const int radius = 500;
internal const int size = 1000;
internal const int center = size / 2;
private double secondAngle = 0;
private double minuteAngle = 0;
private double hourAngle = 0;
private TimeZoneInfo timeZone;
private DateTimeOffset currentSecond;
private readonly System.Timers.Timer timer = new();
[Parameter]
public int Size { get; set; } = 50;
[Parameter]
public string FaceColor { get; set; } = "#f5f5f5";
[Parameter]
public string HourColor { get; set; } = "blue";
[Parameter]
public string MinuteColor { get; set; } = "green";
[Parameter]
public string SecondColor { get; set; } = "red";
[Parameter]
public string TimeZone { get; set; }
protected override void OnInitialized()
{
if (string.IsNullOrWhiteSpace(TimeZone) is true)
{
timeZone = TimeZoneInfo.Local;
}
else
{
timeZone = TimeZoneInfo.FindSystemTimeZoneById(TimeZone);
}
timer.Interval = 100;
timer.Elapsed += Timer_Elapsed;
UpdateClock();
timer.Start();
}
public static DateTime GmtToPacific(DateTime dateTime)
{
return TimeZoneInfo.ConvertTimeFromUtc(dateTime,
TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"));
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
UpdateClock();
InvokeAsync(StateHasChanged);
}
private void UpdateClock()
{
const double radiansPer60 = 360 / 60 * Math.PI / 180;
const double radiansPer12 = 360 / 12 * Math.PI / 180;
var currentTime = TimeZoneInfo.ConvertTime(DateTimeOffset.Now, timeZone);
var roundedSencond = new DateTimeOffset(currentTime.Year, currentTime.Month, currentTime.Day, currentTime.Hour, currentTime.Minute, currentTime.Second, default);
if (roundedSencond != currentSecond)
{
currentSecond = roundedSencond;
var seconds = currentTime.Second;
var minutes = currentTime.Minute;
var hours = currentTime.Hour % 12;
secondAngle = seconds * radiansPer60;
minuteAngle = minutes * radiansPer60 + secondAngle / 60;
hourAngle = hours * radiansPer12 + minuteAngle / 12;
}
}
public void Dispose()
{
if (timer is not null)
{
timer.Dispose();
}
}
}
ClockHand.razor
<line x1="500" y1="500" x2="#X" y2="#Y" style="stroke:#Color;stroke-width:#Width" />
ClockHand.razor.cs
public partial class ClockHand : ComponentBase
{
[Parameter]
public double Angle { get; set; }
[Parameter]
public double Length { get; set; } = 1;
[Parameter]
public string Color { get; set; } = "black";
[Parameter]
public int Width { get; set; }
double X => Math.Sin(Angle) * Clock.radius * Length + Clock.center;
double Y => Math.Cos(Angle) * -Clock.radius * Length + Clock.center;
}
Useage
<Clock TimeZone="Australia/Sydney" />
or
<Clock />
TimerElapsed is not a 'normal' Blazor lifecycle event. So it won't automatically trigger a re-render. (A ButtonClick event would, for example).
So you need to call StatehasChanged, and to cater for the possibility it's on another Thread you need to InvokeAsync that.
private async void Set(object sender, ElapsedEventArgs e)
{
var rng = new Random();
var x = rng.Next(500, 600);
RandomNumberX = x;
await InvokeAsync(StatehasChnaged);
}
You should normally avoid async void but this is exactly the suituation it was created for.
Side note: timer.Elapsed -= Set; during Initialization is only half a solution.
Use #implements IDisposable on the top of your page and add
public void Dispose()
{
timer.Elapsed -= Set;
}

Create a method instance with a parameter

How can I call the parameter which is inside the method instance in the other class, as I want to make a calculation with the method and display it.
class Box
{
int width = 10;
int height = 15;
public int Area(int Area)
{
Area = width * height;
return Area;
}
public int Perimeter(int Para)
{
Para = 2 * (height + width);
return Para;
}
}
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
static void Main(string[] args)
{
Box b = new Box();
b.Area(Area);
b.Perimeter(Para);
Console.ReadLine();
}
It is giving me en error on b.Area(Area); and b.Perimeter(Para);
Maybe you wanted to do this:
class Program
{
static void Main(string[] args)
{
Box box = new Box(10, 15);
Console.WriteLine("Area is: " + box.CalculateArea());
Console.WriteLine("Perimeter is: " + box.CalculatePerimeter());
Console.ReadLine();
}
}
public class Box
{
public int Width { get; set; }
public int Height { get; set; }
public Box(int width, int height)
{
Width = width;
Height = height;
}
public int CalculateArea()
{
return Width * Height;
}
public int CalculatePerimeter()
{
return 2 * (Width + Height);
}
}

How can I display as text the properties of an element in a textbox in windows form application c#?

I am writing a program that calculates keplerian elements. the main function gets 2 lines of tle, and return the object kep and his properties are the parameters of the sattelite orbit. I have to display these parameters in a textbox, but I dont understand how exactly am I supposed to do it.
any help will be appriciated :)
form1.cs:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void inputtext_TextChanged(object sender, EventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void retrieveInput_Click(object sender, EventArgs e)
{
String line1 = line1String.Text;
String line2 = line2String.Text;
//what happens after the recieving of the strings is the calculation and displating the kep properties in textbox "ShowBox"
}
private void textBox1_TextChanged_1(object sender, EventArgs e)
{
}
}
my kepelments class:
class KepElements
{
public double raan { get; set; }
public double argperi { get; set; }
public double meanan { get; set; }
public double meanmotion { get; set; }
public double eccentricity { get; set; }
public double bstar { get; set; }
public double epochYear { get; set; }
public double inclination { get; set; }
public double epochDay { get; set; }
}
and the main program:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
//function that gets 2 strings and calculates all elemnts
public static KepElements calculating(String line1, String line2)
{
double raan, argperi, meanan, meanmotion, eccentricity, bstar, epochYear, inclination, SepochDay, sec, epochDay;
int CurrentSec, sec2, sec3;
KepElements kep = new KepElements();
//setting eccentricity
eccentricity = Convert.ToDouble(line2.Substring(28, 7));
kep.eccentricity = eccentricity;
//setting the bstar
bstar = Convert.ToDouble(line2.Substring(55, 8));
kep.bstar = bstar;
//setting the epochYear
epochYear = Convert.ToDouble(line2.Substring(20, 2));
kep.epochYear = epochYear;
//calculating the EpochDay
SepochDay = Convert.ToDouble(line2.Substring(22, 12));
sec = ((SepochDay - Math.Truncate(SepochDay)) * 100000000); //the time of seconds (after the decimal point)
sec3 = (int)sec;
sec2 = (int)SepochDay;
sec2 = sec2 * 86400;//sec2 is now the number of sec in a day*number of days since beggining of the current year
CurrentSec = (DateTime.Now.Year - 1970) * 31556926;
epochDay = CurrentSec + sec + sec2;
kep.epochDay = epochDay;
//calculating the inclination
inclination = Convert.ToDouble(line2.Substring(10, 8));
inclination = (inclination / 180) * Math.PI;
kep.inclination = inclination;
//calculating the meananomaly
meanan = Convert.ToDouble(line2.Substring(45, 8));
meanan = (meanan / 180) * Math.PI;
kep.meanan = meanan;
//calculating the argue of perigee
argperi = Convert.ToDouble(line2.Substring(36, 8));
argperi = (argperi / 180) * Math.PI;
kep.argperi = argperi;
//calculating the mean motion
meanmotion = Convert.ToDouble(line2.Substring(54, 11));
meanmotion = (meanmotion / 1440) * Math.PI * 2;
kep.meanmotion = meanmotion;
//calculating the raan
raan = Convert.ToDouble(line2.Substring(19, 8));
raan = (raan / 180) * Math.PI;
kep.raan = raan;
return kep;
}
}
You can either manually add all the values with labels using $"Label: {value}\r\n" or use a StringBuilder class. Another option is to use reflection on the class holding the data and build your text output by automatically looking at the properties and their values. Then just assign the built text string to the text box.
You could also use the string override ToString() in your KepElements class.
Requires:
using System.Reflection;
Example:
class KepElements
{
public double raan { get; set; }
public double argperi { get; set; }
public double meanan { get; set; }
[UserFriendlyName("Mean Motion")]
public double meanmotion { get; set; }
public double eccentricity { get; set; }
public double bstar { get; set; }
public double epochYear { get; set; }
public double inclination { get; set; }
public double epochDay { get; set; }
public override string ToString()
{
StringBuilder build = new StringBuilder();
foreach (var property in typeof(KepElements).GetProperties())
{
build.AppendLine($"{property.GetUserFriendlyName()}: {property.GetValue(this)}");
}
return build.ToString();
}
}
[AttributeUsage(AttributeTargets.Property)]
public class UserFriendlyName : Attribute
{
public UserFriendlyName(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public static class GetUserFriendlyNameExt
{
public static string GetUserFriendlyName(this PropertyInfo obj)
{
object[] attribs = obj.GetCustomAttributes(typeof(UserFriendlyName),false);
if (attribs != null && attribs.Length > 0)
return (attribs[0] as UserFriendlyName)?.Name;
else
return obj.Name;
}
}

returning actual Height and Width to wpf rectangle after dynamic change

I have an app with the main window which contains a rectangle and a button that leads to another window in which the user enters information. After entering info, user clicks on a button and it returns him to the main window and changes the size accordingly. What I am trying to achieve is to return the ActualHeight and ActualWidth to the rectangle if a user presses the button in the main window again, kind of a refresh of rectangle.
All the code is in the Main Window Button click event. If you need any specific information about the code, i will gladly give it to you.
private void buttonStart_Click(object sender, RoutedEventArgs e)
{
Questionnaire q = new Questionnaire();
q.ShowDialog();
var size = q.textBoxNumberOfEmployees.Text;
if (int.Parse(size) > 5 && int.Parse(size) < 15)
{
Rect1.Height = Rect1.ActualHeight - 10;
Rect1.Width = Rect1.ActualWidth - 5;
}
else if (int.Parse(size) > 15 && int.Parse(size) < 30)
{
Rect1.Height = Rect1.ActualHeight - 15;
Rect1.Width = Rect1.ActualWidth - 10;
}
else if (int.Parse(size) > 30 && int.Parse(size) < 100)
{
Rect1.Height = Rect1.ActualHeight - 30;
Rect1.Width = Rect1.ActualWidth - 15;
}
else
{
Rect1.Height = Rect1.ActualHeight;
Rect1.Width = Rect1.ActualWidth;
}
You can store the original height and width of rectangle in variables in form load. Use those variables to make rectangle to original size bebore opening new window in button click.
Following code goes at the top inside your form.
private int rect1width;
private int rect1height;
In your form__load you write this at the end.
rect1width = Rect1.ActualWidth;
rect1height = Rect1.ActualHeight;
In your button click code following code goes at top.
Rect1.Width = rect1width;
Rect1.Height = rect1height;
Here is some seemingly long code, but it uses an MVC type design pattern and compounds with the state pattern. The only thing really missing to make it true MVC is Observers and observable interfaces that would subscribe to the Questionnaire.
public interface RectangleState
{
int myHeight { get; set; }
int myWidth { get; set; }
}
public class RectangleModel
{
private static Rectangle Rect1;
public RectangleModel(Rectangle rect1 )
{
Rect1 = rect1;
}
private RectangleState state;
public RectangleState State
{
get
{
return state;
}
set
{
state = value;
ModifyState(value.myHeight, value.myWidth);
}
}
private void ModifyState(int Height, int Width)
{
Rect1.Height = Height;
Rect1.Width = Width;
}
}
public class SmallState : RectangleState
{
public int myHeight { get; set; } = 20;
public int myWidth { get; set; } = 80;
}
public class MediumState : RectangleState
{
public int myHeight { get; set; } = 25;
public int myWidth { get; set; } = 90;
}
public class LargeState : RectangleState
{
public int myHeight { get; set; } = 35;
public int myWidth { get; set; } = 120;
}
public class NormalState : RectangleState
{
public int myHeight { get; set; } = 30;
public int myWidth { get; set; } = 100;
}
Now all you need to do is plug in the conditions:
RectangleModel RM = new RectangleModel(myRectangle); // store this in your class as property;
int size = 0;
int.TryParse(q.textBoxNumberOfEmployees.Text, out size);
if (size > 5 && size < 15)
{
RM.State = new SmallState();
}
else if (size > 15 && size < 30)
{
RM.State = new MediumState();
}
else if (size > 30 && size < 100)
{
RM.State = new LargeState();
}
else
{
RM.State = new NormalState();
}
If later you decide you want to change the default values on any of these you can change them. If you wish to add a new Rectangle shape or size you can add it. If you wish to create an adapter to further modify the rectangle, you can do so. This is a nice pattern. I know the answer looks overdone, but I think you will find it works solidly and is quite flexible when plugged into the code that accesses your questionaire.

Categories

Resources