I am creating a date time picker but for some reason my tap gesture is not showing the date picker am using for the date portion of the control.
public DateTimePicker2()
{
BindingContext = this;
_dayEntry.TextChanged += _dayEntry_TextChanged;
_dayEntry.Focused += _dayEntry_Focused;
_monthEntry.TextChanged += _monthEntry_TextChanged;
_yearEntry.TextChanged += _yearEntry_TextChanged;
Content = new StackLayout()
{
Orientation = StackOrientation.Horizontal,
Children =
{
_dayEntry,
_monthEntry,
_yearEntry,
_hourEntry,
_minsEntry,
_ampmPicker
}
};
The code is getting hit but just not presenting the datpicker I think my control might be hidding it some how.
_datePicker.SetBinding<DateTimePicker2>(DatePicker.DateProperty, p => p._date);
_timePicker.SetBinding<DateTimePicker2>(TimePicker.TimeProperty, p => p._time);
I am using the focus and unfocused events
_timePicker.Unfocused += (sender, args) => _time =
_timePicker.Time;
_datePicker.Focused += (s, a) => UpdateEntryText();
GestureRecognizers.Add(new TapGestureRecognizer()
{
Command = new Command(() => _datePicker.Focus())
});
When the user picks the _day entry textbox lets display the date popup for them.
Dayy entry is just a dynamic entry box.
public Entry _dayEntry { get; private set; } = new Entry() {
TabIndex=0,
Placeholder="Day" ,Keyboard=Keyboard.Numeric, WidthRequest = 60
,HorizontalOptions = LayoutOptions.Start };
Date time pickers are declared as such
public DatePicker _datePicker { get; private set; } = new
DatePicker() { MinimumDate = DateTime.Today, IsVisible = false };
public TimePicker _timePicker { get; private set; } = new
TimePicker() { IsVisible = false };
_dayEntry.Focused += (sender, args) =>
{
Device.BeginInvokeOnMainThread(() => _datePicker.Focus());
};
_datePicker.Unfocused += (sender, args) =>
{
Device.BeginInvokeOnMainThread(() =>
{
_timePicker.Focus();
_date = _datePicker.Date;
UpdateEntryText();
});
};
}
Even if I add isVisble it does not show.
_dayEntry.Focused += (sender, args) =>
{
Device.BeginInvokeOnMainThread(() => {
_datePicker.IsVisible = true;
_datePicker.Focus();
});
};
The problem was that the date time pickers where not added as children that is why their visiblity is set to false ;-)
Content = new StackLayout()
{
Orientation = StackOrientation.Horizontal,
Children =
{
_datePicker, ** Important these must exist **
_timePicker, ** Important these must exist **
_dayEntry,
_monthEntry,
_yearEntry,
_hourEntry,
_minsEntry,
_ampmPicker}
}
};
Related
I create a chart based on data of a GridView, so if a user select a row in my grid view I execute the chart create as:
private void dgvUserActivity_CellClick(object sender, DataGridViewCellEventArgs e)
{
var dg = (DataGridView)sender;
if (e.RowIndex == -1) return;
var selectedrowindex = dg.SelectedCells[0].RowIndex;
var selectedRow = dg.Rows[selectedrowindex];
var selectedUserName = selectedRow.Cells["UserName"].Value.ToString();
UserActivityAuditModel = UserActivityModel.UserActivityAuditList.Where(x => x.UserName == selectedUserName).ToList();
ClearChartPoints();
userChart.Titles.Clear();
LoadChart(UserActivityAuditModel);
}
Then I load chart as:
private void LoadChart(IList<UserActivityAuditViewModel> model)
{
//Filter info
var selectedTime = new List<TimeSpan>();
if (rdoLogOn.Checked)
{
selectedTime = model.Select(x => x.AverageLogOn).ToList();
}
else if (rdoLogOff.Checked)
{
selectedTime = model.Select(x => x.AverageLogOff).ToList();
}
else
{
selectedTime = model.Select(x => x.AverageTotalHours).ToList();
}
Axis XA = userChart.ChartAreas[0].AxisX;
Axis YA = userChart.ChartAreas[0].AxisY;
Series S1 = userChart.Series[0];
S1.ChartType = SeriesChartType.Line;
//Add or change Title
var title = new Title();
title.Font = new Font("Arial", 14, FontStyle.Bold);
title.Text = Helpers.FirstCharToUpper(model.Select(x => x.UserName).FirstOrDefault());
userChart.Titles.Add(title);
var dates = model.Select(x => x.ActivityDate).ToList();
var currentRegister = 0;
foreach (DateTime d in dates)
{
var yValue = selectedTime[currentRegister].ToString();
S1.Points.AddXY(d, yValue);
currentRegister++;
}
var dt = DateTime.Now;
S1.LegendText = "Year " + dt.Year;
// move to the bottom center:
userChart.Legends[0].Docking = Docking.Bottom;
userChart.Legends[0].Alignment = StringAlignment.Center;
if (!rdoTotalHours.Checked)
{
S1.YValueType = ChartValueType.Time;
XA.LabelStyle.Format = "mm:ss";
}
else
{
}
S1.XValueType = ChartValueType.Date;
XA.MajorGrid.Enabled = false;
XA.LabelStyle.Format = "MMM";
XA.IntervalType = DateTimeIntervalType.Months;
XA.Interval = 1;
YA.IsInterlaced = true;
//YA.MajorGrid.Enabled = false;
YA.InterlacedColor = Color.FromArgb(31, Color.LightSeaGreen);
}
For some reason in my first clic of DataGridView it executes the chart create,I debug it and the problem is in this foreach clause :
foreach (DateTime d in dates)
{
var yValue = selectedTime[currentRegister].ToString();
S1.Points.AddXY(d, yValue);
currentRegister++;
}
The value is there, after S1.Points.AddXY(d, yValue); is executed, I debug Points Y value is always 0 but the yValue I set has the correct number!. This is really weird.
Pictures:
As you can see value is there, but when I press F10 to continue debugging:
It added as 0 instead my value
Note: As I say before, this is only first time load, if I clic again in any row, it load correctly, someone have an idea of what is happening there? Regards
----EDIT----
I get the yValue from my global model:
public IList<UserActivityAuditViewModel> UserActivityAuditModel { get; set; } = new List<UserActivityAuditViewModel>();
Then I assign it depending of some radio buttons on the beginning of chart method:
var selectedTime = new List<TimeSpan>();
if (rdoLogOn.Checked)
{
selectedTime = model.Select(x => x.AverageLogOn).ToList();
}
else if (rdoLogOff.Checked)
{
selectedTime = model.Select(x => x.AverageLogOff).ToList();
}
else
{
selectedTime = model.Select(x => x.AverageTotalHours).ToList();
}
and I use that TimeSpan list into yValue
I create a simple test, instead load my Y value with TimeSpan I create an int list as:
var testList = new List<int>();
testList.Add(1);
testList.Add(2);
testList.Add(3);
testList.Add(4);
testList.Add(5);
testList.Add(6);
testList.Add(7);
testList.Add(8);
testList.Add(9);
testList.Add(10);
testList.Add(11);
testList.Add(12);
testList.Add(13);
Then I use in foreach as
foreach (DateTime d in dates)
{
var yValue = testList[currentRegister].ToString();
S1.Points.AddXY(d, yValue);
currentRegister++;
}
And now chart load in first load, but I can not understand why is not working with TimeSpan in first load, can someone have an idea of what is happening and a solution for this?
I found the issue
Charts does not support TimeSpan, so for some reason at the first render of chart it conflicts with Chart data. So the simplest solution I found is to convert TimeSpan to DateTime, at the end of the day we use YValueType as Time so it will take the time of the DateTime and display instead Date:
foreach (DateTime d in dates)
{
var datetime = new DateTime(0).AddSeconds(selectedTime[currentRegister].TotalSeconds);
S1.Points.AddXY(d, datetime);
currentRegister++;
}
So I have a UWP project that I handle bookings on a group of rooms in.
I get all of my values from a Json API.
I want to make like a loop that checks if a room is booked or not every minute or something like that, but I have no idé how to do it.
This is how I get all the rooms with the bookings and all the attributes to them:
public async void addroom()
{
string url = "https://api.booking.com/api/company/07ce8f7c-f3d3-4df2-84bd-33f8fc263deb/rooms";
HttpClient client = new HttpClient();
string response = await client.GetStringAsync(url);
List<Class2> data = JsonConvert.DeserializeObject<List<Class2>>(response);
foreach (Class2 room in data)
{
string booking = $"https://api.booking.com/api/company/07ce8f7c-f3d3-4df2-84bd-33f8fc263deb/rooms/{room.id}/bookings";
HttpClient BookingClient = new HttpClient();
string BookingResponse = await BookingClient.GetStringAsync(booking);
List<Bookings> bookings = JsonConvert.DeserializeObject<List<Bookings>>(BookingResponse);
room.Bookings = bookings;
string id = room.id;
string name = room.name;
int seats = room.seats;
Uri Img = room.ImageUrl;
List<Roomattribute> roomattrib = room.roomAttributes;
var NewRoom = new Room
{
RoomID = id,
RoomName = name,
FrontImage = Img,
Seats = seats,
};
foreach (var books in bookings)
{
string note = books.note;
DateTime TimeFrom = books.timeFrom;
DateTime TimeTo = books.timeTo;
Class2 BookRoom = books.room;
string BookId = books.id;
DateTime Now = new DateTime(2018, 04, 25, 09, 40, 00);
var BeforeEnd = books.timeTo.Subtract(Now).Subtract(TimeSpan.FromMinutes(15));
var BeforeBegin = books.timeFrom.Subtract(Now).Subtract(TimeSpan.FromMinutes(15));
if (books.timeFrom <= Now && books.timeTo > Now)
{
ToRed();
DispatcherTimer ColorTimer = new DispatcherTimer();
ColorTimer.Interval = BeforeEnd;
ColorTimer.Tick += (sender, args) =>
{
ToYellow();
ColorTimer.Stop();
};
ColorTimer.Start();
}
else if (books.timeTo == Now)
{
ToGreen();
}
else
{
DispatcherTimer ColorTimer = new DispatcherTimer();
ColorTimer.Interval = BeforeBegin;
ColorTimer.Tick += (sender, args) =>
{
ToYellow();
ColorTimer.Stop();
};
ColorTimer.Start();
}
}
foreach (var attri in roomattrib)
{
int attriId = attri.id;
string attriName = attri.name;
int attriIcon = attri.icon;
if (room.roomAttributes.Any(a => a.id == 1))
{
NewRoom.Tv = Visibility.Visible;
}
else if (room.roomAttributes.Any(a => a.id != 1))
{
NewRoom.Tv = Visibility.Collapsed;
}
if (room.roomAttributes.Any(a => a.id == 2))
{
NewRoom.Wifi = Visibility.Visible;
}
else if (room.roomAttributes.Any(a => a.id != 2))
{
NewRoom.Wifi = Visibility.Collapsed;
}
if (room.roomAttributes.Any(a => a.id == 3))
{
NewRoom.Projector = Visibility.Visible;
}
else if (room.roomAttributes.Any(a => a.id != 3))
{
NewRoom.Projector = Visibility.Collapsed;
}
if (room.roomAttributes.Any(a => a.id == 4))
{
NewRoom.Wboard = Visibility.Visible;
}
else if (room.roomAttributes.Any(a => a.id != 4))
{
NewRoom.Wboard = Visibility.Collapsed;
}
}
Rooms.Add(NewRoom);
}
}
Right now all of my code is working perfectly (Apart from that the all bookings goes to all of the rooms but that is off topic...) and when a room is unoccupied it has a green LinearGredientBrush and when a room gets booked it is changing color to red and when it is 15 min until the room is unoccupied the color is changing to yellow.
What I need the check for is for example if a room is canceled before the time runs out.
I was thinking that put all of this in a For loop could be a solution:
var BeforeEnd = books.timeTo.Subtract(Now).Subtract(TimeSpan.FromMinutes(15));
var BeforeBegin = books.timeFrom.Subtract(Now).Subtract(TimeSpan.FromMinutes(15));
if (books.timeFrom <= Now && books.timeTo > Now)
{
ToRed();
DispatcherTimer ColorTimer = new DispatcherTimer();
ColorTimer.Interval = BeforeEnd;
ColorTimer.Tick += (sender, args) =>
{
ToYellow();
ColorTimer.Stop();
};
ColorTimer.Start();
}
else if (books.timeTo == Now)
{
ToGreen();
}
else
{
DispatcherTimer ColorTimer = new DispatcherTimer();
ColorTimer.Interval = BeforeBegin;
ColorTimer.Tick += (sender, args) =>
{
ToYellow();
ColorTimer.Stop();
};
ColorTimer.Start();
}
I hope I described the question well enough, and would be very pleased to get some help with my question.
Thanks in advance!
Instead of creating a DispatcherTimer for each booking separately, you could just create a single one that is triggered once per a time interval, for example once per minute (depending on how often you want to see the color changes).
In the Tick handler, you could then just check for each room:
A booking is active: Red - this check can be done by a simple foreach loop over the bookings on the given room
A booking is starting in less than 15 minutes: Yellow - again a simple foreach loop, check the start times of all bookings, if one is less than 15 minutes away, we have a match
Otherwise: Green
The DispatcherTimer.Tick event fires after the time specified in Interval has elapsed. Tick continues firing at the same Interval until the Stop method is called, the app terminates, or the app is suspended (fires Suspending). So you can put the loop here and specify the internal is one minute.
Besides, if you want your app can run while minimized or under the lock screen, you can use extended execution to achieve it. See the topic Postpone app suspension with extended execution.
---Update---
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
//Get current managed thread ID
Debug.WriteLine(Environment.CurrentManagedThreadId);
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMinutes(1);
timer.Tick += async (ob, arg) =>
{
Debug.WriteLine(Environment.CurrentManagedThreadId);
//You can update the booking room color here
//TODO get data and update room color
//You can also update the booking room color using Dispatcher.RunAsync method.
//This is alternative to update the data on the Tick event above TODO part directly .
//await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
//{
// Debug.WriteLine(Environment.CurrentManagedThreadId);
// //TODO get data and update room color
//});
};
timer.Start();
}
You can see the CoreDispatcher.RunAsync(CoreDispatcherPriority, DispatchedHandler) Method.
I have few tables, using Entity Framework 6. My goal is to bind class table1 to ComboBox Value Member
ComboBox DataSource is:
ComboBoxBasicDB[] statType = new ComboBoxBasicDB[] {
new ComboBoxBasicDB { Text = "A1", Value = 0 },
new ComboBoxBasicDB { Text = "A2", Value = 1 },
new ComboBoxBasicDB { Text = "A3", Value = 2 },
new ComboBoxBasicDB { Text = "A4", Value = 4 },
new ComboBoxBasicDB { Text = "B12", Value = 12 },
new ComboBoxBasicDB { Text = "B13", Value = 13 },
new ComboBoxBasicDB { Text = "B14", Value = 14 }
};
statBS.DataSource = statType; // statBS == BindingSource, configured throught VS designer, comboBox.DataSource = statBS, comboBox.ValueMember = Value, comboBox.DisplayMember = Text
table1 contains property called ex. Value1 which contains one of these (0, 1, 2, 4, 12, 13, 14)
What am I trying to do is to load from DB row and use something like this on TextBox:
textBox.DataBindings.Add("Text", binding, "Name");
which works perfectly
I tried something like this:
comboBox.DataBindings.Add("SelectedValue", binding, "Value1");
but it not working, nothing is selected after query. textBox bind successfully
I used SelectedIndex but there is going one problem, and that is value above 7, because there are 7 items in statType not 14.
I hope you understand what am I trying to do :/
I thought I could do that throught comboBox.DataManager but its private
Thanks for any ideas.
So solution is custom implementation, in mentioned DataBindings change SelectedValue to SelectedItemValue
Implementation:
public class ComboBoxBasic : ComboBox
{
bool diffTextColor = false;
public ComboBoxBasic()
{
}
public object SelectedItemValue
{
get
{
return (SelectedItem as ComboBoxBasicDB).Value;
}
set
{
for(int i = 0; i < Items.Count; i++)
{
ComboBoxBasicDB item = Items[i] as ComboBoxBasicDB;
if(item.Value.ToString() == value.ToString())
{
SelectedIndex = i;
break;
}
}
}
}
public bool DifferentTextColor
{
get { return diffTextColor; }
set
{
diffTextColor = value;
if (diffTextColor)
{
DrawItem += ComboBoxBasic_DrawItem;
DrawMode = DrawMode.OwnerDrawFixed;
}
else
DrawItem -= ComboBoxBasic_DrawItem;
}
}
void ComboBoxBasic_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
if (e.State == DrawItemState.Focus)
e.DrawFocusRectangle();
Brush brush = new SolidBrush((sender as Control).ForeColor);
ComboBoxBasicDB item = (sender as ComboBoxBasic).Items[e.Index] as ComboBoxBasicDB;
if (item.ForeColor != Brushes.Black)
brush = item.ForeColor;
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
e.Graphics.DrawString(item.Text, (sender as Control).Font, brush, e.Bounds.X, e.Bounds.Y);
}
}
Also there is custom DrawItem if its enabled by DifferentTextColor
I am using Dotnet Highchart that is based on C# code that has output code javascript.
Dotnet HighChart
This is almost how my chart looks like:
I am using data from my database to give this chart data by using LINQ queries.
I have a column "Completed Date" in my entity and I need to make two textboxes with datepicker so user can choose Start and end dates of Completed Date.Then the user should be able to click on a submit button and then the chart should update and show the statistic between the two dates. I have the complete LINQ Query for this
This is the LINQ query that I am going to use:
public List<CoreValueAndAverageGrade> GetAverageGradeForAllCoreValues(DateTime startDate, DateTime endDate)
{
return db.CoreValue
.Where(coreValue => coreValue.CoreValueQuestion
.Any(coreValueQuestion => coreValueQuestion.SubjectType.Ignored_Statistic == false))
.Select(coreValue => new CoreValueAndAverageGrade
{
CoreValue = coreValue,
AverageGrade = coreValue.CoreValueQuestion
.Where(coreValueQuestion => coreValueQuestion.SubjectType.Ignored_Statistic == false)
.Average(coreValueQuestion => coreValueQuestion.SelectedQuestions
.Where(selectedQuestion => selectedQuestion.GoalCardQuestionAnswer != null
&& selectedQuestion.GoalCardQuestionAnswer.Grade.HasValue
&& selectedQuestion.GoalCard.Completed_Date >= startDate
&& selectedQuestion.GoalCard.Completed_Date <= endDate
)
.Average(selectedQuestion => selectedQuestion.GoalCardQuestionAnswer.Grade.Value))
})
.ToList();
}
This is my ViewModel
public class OfficeStatisticNKIViewModel
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
In my GET action method I have following code:
public ActionResult OfficeStatistic()
{
{
OfficeStatisticNKIViewModel model = new OfficeStatisticNKIViewModel();
model.EndDate = DateTime.Now;
model.StartDate = DateTime.Now;
var averageGrades = OfficeStatisticRepository.GetAverageGradeForAllCoreValues(model.StartDate, model.EndDate);
var dataItems = (averageGrades.Select(averageGrade => averageGrade.AverageGrade).ToArray());
Data data = new Data(
dataItems.Select(y => new Point {Color = GetBarColour(y), Y = y}).ToArray());
Highcharts chart1 = new Highcharts("Chart")
.SetXAxis(new XAxis { Categories = averageGrades.Select(averageGrade => averageGrade.CoreValue.Name).ToArray() })
.SetYAxis(new YAxis { Min = 0, Max = 10, TickInterval = 1, Title = new YAxisTitle { Text = "Betygskalan" } })
.SetSeries(new Series { Data = data, Name = "Snittbetyg" })
.SetLegend(new Legend { Enabled = false })
.SetTitle(new Title { Text = "Örebro Statistik", })
.InitChart(new Chart { DefaultSeriesType = ChartTypes.Column });
return View(new Container(new[] { chart1 }));
}
The problem is that I have no idea how to do the post action method, The chart needs to update with the new the statistic, do I need some kind of ajax or can I do this on the serverside?
Any kind of help or tips is very appreciated!
Thanks in advance!
http://dotnethighcharts.codeplex.com/discussions/350721/
I am using Dotnet Highchart with MVC3
I am currently working with a diagram that looks like this:
I am trying to modify my code so I can change color on the bars depending on what number they have. I also wonder how I can remove the button "Snittbetyg" as you see can on the image.
This is my code:
public ActionResult OfficeStatistic()
{
{
Highcharts chart1 = new Highcharts("chart1")
.SetXAxis(new XAxis { Categories = new[] { "Ödmjukhet", "Engagemang", "Kompetens", "Lönsamhet" } })
.SetYAxis(new YAxis { Title = new YAxisTitle { Text = "Betygskalan" } })
.SetSeries(new Series { Data = new Data(new object[] { 1, 8, 9, 6 }), Name = "Snittbetyg" })
.SetTitle(new Title { Text = "Örebro Statistik" })
.InitChart(new Chart { DefaultSeriesType = ChartTypes.Column });
return View(chart1);
}
}
Any kind of help is appreciated.
Thanks in advance!
I haven't used Highchart but you can download examples from their codeplex page. It looks like both of your requirements can be achieved easily.
Remove the "Snittbetyg" button
Disable the legend:
.SetLegend(new Legend { Enabled = false });
Add Colours
For the series data use points instead of just the numbers:
Data data = new Data(new[]
{
new Point { Y = 1, Color = System.Drawing.Color.Red },
new Point { Y = 8, Color = System.Drawing.Color.Blue },
new Point { Y = 9, Color = System.Drawing.Color.Green },
new Point { Y = 6, Color = System.Drawing.Color.Black }
});
Highcharts chart1 = new Highcharts("chart1")
.SetXAxis(new XAxis { Categories = new[] { "Ödmjukhet", "Engagemang", "Kompetens", "Lönsamhet" } })
.SetYAxis(new YAxis { Title = new YAxisTitle { Text = "Betygskalan" } })
.SetSeries(new Series { Data = data, Name = "Snittbetyg" })
.SetTitle(new Title { Text = "Örebro Statistik" })
.InitChart(new Chart { DefaultSeriesType = ChartTypes.Column })
.SetLegend(new Legend { Enabled = false });
There doesn't seem to be a built in way to make highchart automatically colour the bar based on the y-value. I believe you would have to pick the colour yourself, e.g:
private System.Drawing.Color GetBarColour(int value)
{
if (value < 5) return System.Drawing.Color.Red;
if (value > 7) return System.Drawing.Color.Green;
return System.Drawing.Color.Orange;
}
public ActionResult OfficeStatistic()
{
{
var dataItems = new[] {1, 8, 9, 6};
Data data = new Data(
dataItems.Select(y => new Point {Color = GetBarColour(y), Y = y}).ToArray()
);
Highcharts chart1 = new Highcharts("chart1")
.SetXAxis(new XAxis { Categories = new[] { "Ödmjukhet", "Engagemang", "Kompetens", "Lönsamhet" } })
.SetYAxis(new YAxis { Title = new YAxisTitle { Text = "Betygskalan" } })
.SetSeries(new Series { Data = data, Name = "Snittbetyg" })
.SetTitle(new Title { Text = "Örebro Statistik" })
.InitChart(new Chart { DefaultSeriesType = ChartTypes.Column })
.SetLegend(new Legend { Enabled = false });
First, define a Tuple list first item is for color and second item point value
List<Tuple<string, Object>> dataItems = new List<Tuple<string, Object>>();
i am passing value with swtich it is not neccessary
SqlDataReader reader = myComm.ExecuteReader();
if (reader.HasRows)
{
string colorName ="";
while (reader.Read())
{
switch ((string)reader.GetValue(1))
{
case "Total Employee(s)":
colorName = "Blue";
break;
case "Present":
colorName = "Green";
break;
case "Late":
case"Absent":
case "During Less":
case "Early Going":
colorName = "Red";
break;
case "Leave":
colorName = "Orange";
break;
default:
colorName = "Gray";
break;
}
dataItems.Add(new Tuple<string, Object>(colorName, reader.GetValue(2)));
}
Now, Finally add Data into series object
new Series{
Name = "Employees",
Data = new Data(
dataItems.Select(y => new Point {
Color = System.Drawing.Color.FromName(y.Item1),
Y = (int)y.Item2 }).ToArray()
)
}