WPF charting DateTimeAxis issue? - wpf

I created a graph with column series by using data visualization and in that i've taken DateTimeAxis as x-axis and i've one combo box with time intervals and based on selection of combo box i need to bind intervals into my graph at runtime. The problem is i'm getting error if i select intervals randomly like
var xAxis = countChart.ActualAxes.OfType<DateTimeAxis>().FirstOrDefault(ax => ax.Orientation == AxisOrientation.X);
xAxis.Minimum = DateTime.Parse(fromDt.ToString("HH:mm:ss"));
xAxis.Maximum = DateTime.Parse(toDt.ToString("HH:mm:ss"));
"The minimum value must be smaller than or equal to the maximum value."
so how can i overcome my problem plz help me.
Thanks,
#Nagaraju.

Check and modify the Minimum and Maximum properties as needed.
Don't use fallback values in binding, but control the dates set by yourself. If you're not using view model, you could use the setter logics in code-behind.
<charting:DateTimeAxis
Orientation="X"
IntervalType="{Binding IntervalType, FallbackValue=Years}"
Interval="{Binding Interval}"
Maximum="{Binding EndDate}"
Minimum="{Binding StartDate}" />
public DateTime StartDate
{
get { return _startDate; }
set
{
if (EndDate < value)
{
EndDate = value;
}
// Set property and notify that property has changed
//...
}
}
private DateTime _endDate;
public DateTime EndDate
{
get { return _endDate; }
set
{
if (StartDate > value)
{
StartDate = value;
}
// Set property and notify that property has changed
//...
}
}

What may be happening here is the new Minimum value you are setting is larger than the old Maximum, so at the line xAxis.Minimum = .. you get an exception. Can you try this as a workaround (also to prove this theory)? Just change the order that you are setting the min/max on the XAxis.
So, use this:
xAxis.Maximum = DateTime.Parse(toDt.ToString("HH:mm:ss")); // Set max first
xAxis.Minimum = DateTime.Parse(fromDt.ToString("HH:mm:ss"));
instead of this:
xAxis.Minimum = DateTime.Parse(fromDt.ToString("HH:mm:ss"));
xAxis.Maximum = DateTime.Parse(toDt.ToString("HH:mm:ss"));
This ensures that the maximum is always larger, so long as your parsed toDT value is larger than the parsed fromDT
Best regards,

i found solution my self..
reset max with tomorrow and min with yesterday.. 'll fix the issue.. like..
xAxis.Minimum = DateTime.Now.AddDays(-1);
xAxis.Maximum = DateTime.Now.AddDays(1);

Related

What is correct to store UpdatedAt or ExpireAt timestamps to limit updates by timeout

I need to implement function to store some value with limit on updates once per week.
I'm implemented in following way:
class Example
{
//Stored in db
public int _value;
//Stored in db
public DateTime _updatedAt;
//Stored in db
public DateTime _canUpdateAfter;
//Constant in code
public TimeSpan _updateTimeout = TimeSpan.FromMinutes(1);
public void StoreValue1(int value)
{
if (DateTime.Now - _updatedAt < _updateTimeout)
{
return;
}
_value = value;
_updatedAt = DateTime.Now;
}
public void StoreValue2(int value)
{
if (_canUpdateAfter > DateTime.Now)
{
return;
}
_value = value;
_canUpdateAfter = DateTime.Now + _updateTimeout;
}
}
I have two ways of implementing it:
Store updated time in db and calculate if timeout is passed in .net code.
Store value when timeout expire in db and compare it with current in .net code.
Which to use and why?
Both solutions are valid.
The only difference between the ways is the time to decide to set the possibility of the next update.
With solution 1 you make the decision every on code evaluation, with others you force the decision on the past.
I prefer solution 1; is more flexible, and sustainable.
Keep in mind the case of your business change update frequency. With solution 1 are enough new code deploy or change one row of your hypothetical configuration table, whereas whit solution 2 you will need to update all rows of the table.

Binding from integer number of days to the WPF UserControl showing both value and unit (Day, Week, Month)

In our WPF application which follows MVVM pattern, there is one property in the ViewModel, which is an integer value representing the number of days. And we would like to present this value in such pattern in WPF: it should contain one TextBox and one ComboBox, where the text in TextBox represents the values of the time and the value in ComboBox represents the unit. For example, property value 5 will show as [5][Day], while value 14 shows as [2][Week]. This should be a two-way binding since we want the user to modify it too. Of course such mapping is not one-to-one, 14 can also be represented to [14][Day]. But the principle is the bigger unit has higher priority.
Now weirdly I don't even know what to start with, especially when I want to follow MVVM. Because I only have one value which binds to to destination. And since it is such a simple value, there is no point to create a class as the DataContext of such UserControl
Anyone can give me some hint? Thanks!
All this work should be done in ViewModel, make the initial integer property private, add two new properties UnitsCount and UnitsType.
private UnitsTypeEnum unitsType = UnitsTypeEnum.Days;
private int unitsCount = 0;
public int UnitsCount
{
get { return unitsCount; }
set
{
/* set the number of days based on this new value and UnitsType */
unitsCount = value;
NotifyPropertyChanged("UnitsCount");
}
}
public UnitsTypeEnum UnitsType
{
get { return unitsType; }
set
{
/* set the number of days based on this new value and UnitsCount */
unitsType = value;
NotifyPropertyChanged("UnitsType");
}
}
Now make sure in constructor you initialize correctly the UnitsCount and UnitsType properties for the first time.

Sort Group summary in Xaml Infragistics grid

I have requirement to sort group summary field.
Ex. I have 3 columns in the grid.
Step 1 : I have group by Id by dragging the Id column in Group by area.
Step 2: Add Sum,Count,Average on column.
Now i want to sort sum or count or average by clicking on that ,so that the whole grouped is sorted by sum like 100,200,300.
please help
The sort order is controlled by the GroupByComparer of the FieldSettings class and this can be accomplished by creating a custom IComparer for the field that is grouped. Note that grouping is actually also a sort so I am going to assume that you still want the default sort to happen when the column is first grouped.
In the following example group by records can be sorted by a single summary result when it is clicked on. This was accomplished by using a custom IComparer for the groups that sorts by the value of the tag if it is set and if not set falls back to the value of the group by record:
public class SummarySortComparer : IComparer
{
public int Compare(object x, object y)
{
GroupByRecord xRecord = x as GroupByRecord;
GroupByRecord yRecord = y as GroupByRecord;
IComparable xValue = xRecord.Value as IComparable;
object yValue = yRecord.Value;
if (xRecord.Tag != null)
{
xValue = xRecord.Tag as IComparable;
yValue = yRecord.Tag;
}
return xValue.CompareTo(yValue);
}
}
This is set on the grid using the following:
this.XamDataGrid1.FieldSettings.GroupByComparer = new SummarySortComparer();
Use the PreviewMouseLeftButtonDown of the grid to get the summary that was clicked on if there was one and set the tag of the group by records to be the value of that summary and refresh the sort of the grid:
void XamDataGrid1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
SummaryResultPresenter summaryResultPresenter =
Utilities.GetAncestorFromType(e.OriginalSource as DependencyObject, typeof (SummaryResultPresenter), false) as
SummaryResultPresenter;
if (summaryResultPresenter != null)
{
GroupBySummariesPresenter groupBySummariesPresenter =
Utilities.GetAncestorFromType(summaryResultPresenter,
typeof(GroupBySummariesPresenter), false) as GroupBySummariesPresenter;
if (groupBySummariesPresenter != null)
{
SummaryResult summaryResult = summaryResultPresenter.SummaryResult;
int summaryResultIndex = summaryResult.ParentCollection.IndexOf(summaryResult);
foreach (GroupByRecord groupRecord in groupBySummariesPresenter.GroupByRecord.ParentCollection)
{
groupRecord.Tag = groupRecord.ChildRecords.SummaryResults[summaryResultIndex].Value;
}
this.XamDataGrid1.Records.RefreshSort();
}
}
}
Note that there are a few limitations in this example in that I haven't implemented any way to clear what summary is sorted so that is something that if desired would still need to be implemented by you. I also didn't include logic to change the sort direction and used the direction that the field is currently sorted by so if you also want to update the direction this will need to be added as well.

format datetimepicker in datagridview column

I am trying to use the DateTime picker custom gridview column type from this MSDN example on How to host controls in DataGridViewCells. I want to display hour and minute in 24 hour format, without seconds or AM PM indicators.
I have set EditingControlFormattedValue to "HH:mm", and when not actually editing the value is displayed correctly.
When editing, if in the constructor of the CalendarEditingControl I set the editing control to CustomFormat = "HH:mm", the control displays the day of week and month. (!?)
When I instead use Format = DateTimePickerFormat.Time, the control shows AM or PM when editing.
How can I persuade this control to display only the parts of the DateTime value that I care about? (C#, VS 2008)
There are a few tweaks you need to to do the linked code to make it work the way you want:
Comment out the hard-coded line in CalendarCell() constructor (this.Style.Format = "d";)
Tell the CalendarEditingControl to use your custom-specified format:
In the designer, set the format you want (EditColumns->DefaultCellStyle->Format)
public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
{
this.Format = DateTimePickerFormat.Custom;
this.CustomFormat = dataGridViewCellStyle.Format;
// ... other stuff
}
I found I needed to make the following changes:
In the constructor of the CalendarCell change the format to 24 hour.
public CalendarCell()
: base()
{
// Use the 24hr format.
//this.Style.Format = "d";
this.Style.Format = "HH:mm";
}
In the constructor for the editing control specify to use a custom format. I've also taken the liberty of setting ShowUpDown true so you don't show the calendar icon when editing the cell:
public CalendarEditingControl()
{
//this.Format = DateTimePickerFormat.Short;
this.Format = DateTimePickerFormat.Custom;
this.CustomFormat = "HH:mm";
this.ShowUpDown = true;
}
Change EditingControlFormattedValue. This doesn't appear to actually be necessary but feels icky to leave as is.
// Implements the IDataGridViewEditingControl.EditingControlFormattedValue
// property.
public object EditingControlFormattedValue
{
get
{
//return this.Value.ToShortDateString();
return this.Value.ToString("HH:mm");
}
set
{
if (value is String)
{
try
{
// This will throw an exception of the string is
// null, empty, or not in the format of a date.
this.Value = DateTime.Parse((String)value);
}
catch
{
// In the case of an exception, just use the
// default value so we're not left with a null
// value.
this.Value = DateTime.Now;
}
}
}
}

object not set to instance of an object!! ComboBox SelectedIndex SelectedItem

I am developing a program which gets all Clearcase regions (basically strings) & adds them to Combo box. I compare an existing clearcase region string in newly added items in combo box & if it is found then I want to select it, but because nothing is selected for the first time, selectedItem is null & selectedIndex = -1.
when I assign 0 to selectedIndex, error comes --> object not set to instance of an object!! same problem when you assign something to selectedItem; gives an error.
whats wrong with my code?
private void PopulateClearCaseRegionComboBox ( )
{
clearCaseRegionComboBox.Items.Clear();
foreach ( Match token in RegularExpression.Match( "\\w+", clearTool.CmdExec( "lsregion" ) ) )
{
clearCaseRegionComboBox.Items.Add(token.Value.Trim());
if (clearCaseRegion.ToUpperInvariant() == token.Value.Trim().ToUpperInvariant())
{
clearCaseRegionComboBox.SelectedIndex = clearCaseRegionComboBox.Items.IndexOf(token.Value.Trim());
}
}
clearCaseRegionComboBox.Sorted = true;
}
A notification: the SelectedIndexChanged event also occurs when you set SelectedIndex or SelectedItem. So if you have something there, check it out also. :) I've passed several hours on it, because you don't see it while debugging.
Are you sure the following line returns a valid index?
clearCaseRegionComboBox.Items.IndexOf(token.Value.Trim());
The Add method returns the index of the newly added item. You can use that value inside your if statement.
private void PopulateClearCaseRegionComboBox ( )
{
clearCaseRegionComboBox.Items.Clear();
foreach ( Match token in RegularExpression.Match( "\\w+", clearTool.CmdExec( "lsregion" ) ) )
{
int index = clearCaseRegionComboBox.Items.Add(token.Value.Trim());
if (clearCaseRegion.ToUpperInvariant() == token.Value.Trim().ToUpperInvariant())
{
clearCaseRegionComboBox.SelectedIndex = index;
}
}
clearCaseRegionComboBox.Sorted = true;
}
Perhaps you can reveal more of your code in context? I say this because it would seem impossible to get this error at this point in your representative code. You've already used the object to add an item 3 lines up.
Are you sinked to any events on the combo box that would assign the clearCaseRegionComboBox variable to null?

Resources