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.
Related
I need to know which row I selected and get value of cell(Ex:idproduct) before to click Edit button.
As #brendon is referring to, if gridView is the current View on your GridControl:
// Get your currently selected grid row
var rowHandle = gridView.FocusedRowHandle;
// Get the value for the given column - convert to the type you're expecting
var obj = gridView.GetRowCellValue(rowHandle, "FieldName");
You can use the GridView's GetRowCellValue method to retrieve the focused row value.
http://documentation.devexpress.com/#windowsforms/DevExpressXtraGridViewsGridGridView_GetRowCellValuetopic
See also: http://documentation.devexpress.com/windowsforms/CustomDocument753.aspx
public int idproductx;
public void tProductGridView_RowClick(object sender, RowClickEventArgs e)
{
if (e.Clicks > 0)
{
idproductx = (int)((GridView)sender).GetRowCellValue(e.RowHandle, "idproduct ");
}
}
I am using GWT combobox with Select item (dropdown checkbox)
I want to make some items defaultly checked, but i cant find any solutions..
#Override
protected void success(List<warehouseDTO> t)
{
warehouse_list = t;
for (int i = 0; i < warehouse_list.size(); i++)
{
whl.put(warehouse_list.get(i).getId() + "", warehouse_list.get(i).getName());
}
selectItemMultiplePickList.setValueMap(whl);
selectComboForm.setItems(selectItemMultiplePickList);
}
On new "Article" (thing in warehouse) its good, but on edit i need to have checked by default.
Maybe its posible with setAttribute but cant find list of attributes.
Thanks
You should use the following:
setValues(values);
Here values accepts multiple String values.
Now as you're doing:
whl.put(warehouse_list.get(i).getId() + "", warehouse_list.get(i).getName());
your key for the combobox will be warehouse_list.get(i).getId() and value will be warehouse_list.get(i).getName().
So to show multiple values as selected values, you need to pass multiple warehouse_list.get(i).getId() as values.
For example, if you want show first 3 values as selected, you can do the following:
selectItemMultiplePickList.setValues(
warehouse_list.get(0).getId(),
warehouse_list.get(1).getId(),
warehouse_list.get(2).getId());
I have 10 comboBox in a groupBox
for I just want to display a calculated value in respective comboBox like this say if I set a varible double i=08.00; then on button click cmboBox should display values like this
CB1-08.00
CB2-09.50
CB3-10.00
CB4-10.50
CB5-11.00
CB6-11.50
.... and so on upto CB10 But I am getting output like this
And Code
private void button1_Click(object sender, EventArgs e)
{
double i=08.00;
foreach (var comboBox in groupBox1.Controls.OfType<ComboBox>())
{
comboBox.Text = i.ToString("00.00");
i = i + 0.5;
}
}
Your combobox order is different in the collection so it inserts the numbers randomly. May be you can name your combobox for instance like cmb1,cmb2,cmb3 etc. and if you update your code it will run.
Your controls in the Controls collection are not sorted by their appearance on the form. You will need to find a way to sort them if you need different values in each based on their position.
Foreach loop doesn't give the collection in the order you wanted. The way to go forward is to give a tag id to each combo box, then you can use that to assign a value to them them.
So your first combo box will start with tag id 0, and the last one will have 8,
double val = 08.00;
for (int i = 0; i < groupBox1.Controls.Count; ++i)
{
var combobox = groupBox1.Controls[i] as ComboBox;
int tag = int.Parse(combobox.Tag.ToString());
double value = val + (0.5 * tag);
combobox.Text = value.ToString("00.00");
}
Make sure you tag the cobbo box in the order you wanted them.
Using Windows forms and linq to Sql, I bound a datagridview to Products Table, I added to the form 1 Textbox to input the searched text.
I wonder how to position the datagridview according to the text entered to find a given ProductName.
Here I do not want to filter rows, I only want to reposition datagrid after each character entered, the used code:
private void textBox1_TextChanged(object sender, EventArgs e)
{
var searchValue = textBox1.Text.Trim().ToUpper();
var qry = (from p in dc.Products
where p.ProductName.ToUpper().StartsWith(searchValue)
select p).ToList();
int itemFound = productBindingSource.Find("ProductName", searchValue);
productBindingSource.Position = itemFound;
}
The execution of code give the next error: System.NotSupportedException was unhandled at the ligne:
int itemFound = productBindingSource.Find("ProductName", searchValue);
Any idea please ?
The MSDN documentation for BindingSource has the answer:
The Find method can only be used when the underlying list is an
IBindingList with searching implemented. This method simply refers the
request to the underlying list's IBindingList.Find method. For
example, if the underlying data source is a DataSet, DataTable, or
DataView, this method converts propertyName to a PropertyDescriptor
and calls the IBindingList.Find method. The behavior of Find, such as
the value returned if no matching item is found, depends on the
implementation of the method in the underlying list.
When you call this method on a BindingSource whose underlying data source does not implement IBindingList then you see the exception (thrown by the default implementation of IBindingList.FindCore:
System.NotSupportedException: The specified method is not supported.
You don't show what you bind the binding source to but clearly it doesn't implement this method.
Annoyingly, BindingList<T> the recommended list type to use for your data source does not provide a FindCore implementation.
If you are using BindingList you will need to create your own custom type. Here is the code for an absolutely bare bones implementation of a BindingList that supports find:
public class FindableBindingList<T> : BindingList<T>
{
public FindableBindingList()
: base()
{
}
public FindableBindingList(List<T> list)
: base(list)
{
}
protected override int FindCore(PropertyDescriptor property, object key)
{
for (int i = 0; i < Count; i++)
{
T item = this[i];
if (property.GetValue(item).Equals(key))
{
return i;
}
}
return -1; // Not found
}
}
You can do lots with your own implementations of BindingList such as supporting sorting. I've left my answer as just the minimum to support the find method. Search for SortableBindingList if you want to know more.
To use this class do something like this:
var qry = (from p in dc.Products
where p.ProductName.ToUpper().StartsWith(searchValue)
select p).ToList();
FindableBindingList<YourType> list = new FindableBindingList<YourType>(qry);
dataGridView1.DataSource = list;
In DataGridView, how to bind an array or list (with n elements) to n DataGridViewTextBoxColumn's?
Maybe it's not so clear, for example, I have a class:
public class DynamicNumberFieldsClass
{
public string FullName { get; set; }
public int[] Years { get; set; }
}
The expected form a DataGridView should display:
FullName Year1 Year2 Year3...
Peter 11 12 13
Bryan 21 22 23
If I have to use reflection, it's okay for me.
Any idea?
Thanks!
Peter
P.S.: We can assume the array field will never be null.
we can even assume that the number of elements in the array is fixed once a session is started, but the user can change it in Settings, so in the next session, the number of elements might not be the same.
I am assuming you are working in Windows Forms. I was able to at least display the data in the format you've shown by putting the DataGridView in Virtual Mode. You had best follow the entire walkthrough for a complete solution, but here is what I did in a quick test (hacked up from the samples in the walkthough):
CellValueNeeded handler:
private void dataGridView1_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
// If this is the row for new records, no values are needed.
if (e.RowIndex == this.dataGridView1.RowCount - 1) return;
DynamicNumberFieldsClass objectInRow = (DynamicNumberFieldsClass)this._people[e.RowIndex];
// Set the cell value to paint using the DynamicNumberFieldsClass object retrieved.
switch (this.dataGridView1.Columns[e.ColumnIndex].Name)
{
case "FullName":
e.Value = objectInRow.FullName;
break;
default:
e.Value = objectInRow.Years[e.ColumnIndex - 1];
break;
}
}
where _people is a collection of DynamicNumberFieldsClass.
Form Load:
private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.VirtualMode = true;
this.dataGridView1.CellValueNeeded += new DataGridViewCellValueEventHandler(dataGridView1_CellValueNeeded);
// Add columns to the DataGridView.
DataGridViewTextBoxColumn fullNameColumn = new
DataGridViewTextBoxColumn();
fullNameColumn.HeaderText = "FullName";
fullNameColumn.Name = "FullName";
this.dataGridView1.Columns.Add(fullNameColumn);
for (int i = 0; i < _numYears; i++)
{
DataGridViewTextBoxColumn yearIColumn = new
DataGridViewTextBoxColumn();
yearIColumn.HeaderText = "Year" + (i+1);
yearIColumn.Name = "Year" + (i+1);
this.dataGridView1.Columns.Add(yearIColumn);
}
this.dataGridView1.AutoSizeColumnsMode =
DataGridViewAutoSizeColumnsMode.AllCells;
// Set the row count, including the row for new records.
this.dataGridView1.RowCount = 3; //two objects in _people and the empty row
}
where _numYears is the fixed value you mentioned. If you have at least one instance of the object available, you could use the size of the Years array in that instance as the loop limiter, so that it is completely dynamic.
You would need to expand the switch statement if any other properties are included in the class, and of course add more error checking in general. The walkthrough shows how to support editing in the DataGridView, as well.
(I know you asked how to bind the columns, not force their values, so you probably wanted to be able to decorate the class definition, assign the data source, and go. To that end, I first looked into doing this with Reflection via CustomTypeDescriptor and TypeDescriptionProvider, etc., which is how second-level properties can be bound. Of course, the individual elements of the array are not exposed as properties, so this doesn't work. I can't think of a way to support auto-generation of the columns the way you want, but maybe someone else will find one.)