I have specific case of grouping items in ObjectListView. Usually one would choose column that is shown in the list and do GroupKeyGetter/GroupKeyToTitleConverter magic on that column. However, in my case the data I would like to group on is not supposed to be shown in ObjectListView. It exists only in Model. So far the only dirty workaround I've found is to make this data shown in ObjectListView, but set width of column 0.
Is there better way to group by data, which is not supposed to be shown in the view?
You can hide your column:
OLVColumn column = new OLVColumn("HiddenGroupColumn", "ModelProperty");
column.IsVisible = false;
column.GroupKeyGetter = delegate(object x)
{
return ((Model)x).ModelProperty;
};
Related
I have 2 listBoxes with BindingLists as their data sources. The idea is to make a List builder (as MSDN names it), where first listBox shows currently added columns and second listBox shows the rest of available columns. First list contains ViewColumn objects, while the other list contains strings.
I load chosen columns into first listBox from database and then I want to load the rest of available columns into the second listBox (the list itself comes from another place in database). Considering there are no limits on the number of columns, I want to do that in the fastest way possible - what would that be?
Here's some code to visualize that:
ViewTable _view;
BindingList<ViewColumn> _viewColumns = new BindingList<ViewColumn>();
BindingList<string> _detailsColumns = new BindingList<string>();
void CustomInitialize()
{
_view = //get view and its columns
_viewColumns = new BindingList<ViewColumn>(_view.Columns);
listBox_CurrentColumns.DataSource = _viewColumns;
listBox_CurrentColumns.DisplayMember = "Name";
var detailsTable = //get the list of available columns
foreach (var row in detailsTable)
{
//TODO: if _viewColumns does not contain this value, add it to _detailsColumns
_detailsColumns.Add(row.ColumnName);
}
listBox_AvailableColumns.DataSource = _detailsColumns;
}
I think you want to do something like:
_detailsColumns = _allColumns.Except(_viewColumns.Select(c => c.Name))
This should get you all entries in the _allColumns collection excluding the entries in the _viewColumns collection.
I assume here that _allColumns contains the overall collection of possible columns.
We've got problem with filtering for some of our columns in devexpress gridcontrol. We add the column dynamically (bound-type column) to the grid. The values from the source objects are long type. In the cells it seems that values are fine (since they're aligned to the right without any custom formating on our side) however in filter popup values behave like strings.
For example data set like 1,2,5,11,22,37 the filter list is sorted like 1,11,2,22,5,37 (just like strings) and when we choose one of the available values the filtering does not work (i mean, grid becames empty). Even filters like "Non empty cells" does not work, but when we choose "empty cells" only few from few thousand rows are shown even if most of the cells have no values.
It is important to point out that only dynamically added columns behave that way, the few columns we create every time our module runs work as intended.
The data source is a container (List like).
We're using DevExpress 13.2.
Example of creating 'custom column'
void CreateColumn(GridColumn gridColumn, string fieldName = null, string caption = null, bool visible = true,
bool readOnly = true, UnboundColumnType unboundType = UnboundColumnType.Bound,
int columnWidth = int.MinValue, int minColumnWidth = int.MinValue)
{
gridColumn.Caption = caption;
if (fieldName != null)
gridColumn.FieldName = fieldName;
gridColumn.Visible = visible;
gridColumn.OptionsColumn.ReadOnly = readOnly;
gridColumn.OptionsColumn.AllowEdit = !readOnly;
gridColumn.UnboundType = unboundType;
gridColumn.OptionsFilter.AllowAutoFilter = true;
gridColumn.FilterMode = ColumnFilterMode.Value;
gridColumn.OptionsFilter.AutoFilterCondition = DevExpress.XtraGrid.Columns.AutoFilterCondition.Contains;
if (columnWidth != int.MinValue)
{
gridColumn.Width = columnWidth;
gridColumn.OptionsColumn.FixedWidth = true;
}
if (minColumnWidth != int.MinValue)
gridColumn.MinWidth = minColumnWidth;
}
GridColumn gridColumn = new GridColumn();
CreateColumn(gridColumn, "someName", "someCaption", true, true);
View.Columns.Add(newGridColumn);
That's how it goes in our code (striped most of not related code just to give example process).
#edit
There's invalid cast exception when we add filter like this:
ColumnFilterInfo filter = GetFilter(); //cant really post code of this
ourGrid.MainView.ActiveFilter.Add(column, filter); // VS points here
Unfortunately it doesnt say what and where (except some 'lambda expression') exception is being thrown.
Of course column is the column mentioned above.
#edit
I've found new "tip". The FilterItem objects contain strings for sure, however they should contain long values. How can we influence the creation of these or atleast where to check why those are created like that (we dont do it manually)?
#Edit 19.11.2015
Alright, I had some breakthrough. The columns ('custom') thanks to our mechanism guess their type just fine. Then only problem is that infact our values which custom columns use are stored in Dictionary<string,object>-like collection and we think that thanks to PropertyDescriptor type for columns is fine, but for some reason FilterItem objects have Value of string. We belive that's because DX filter mechanism can't really guess type of "object" so it uses simple ToString on it so FilterItem.Value is string type instead column's data type.
How to overcome this?
We've found the solution and the mistake was on our side. Column creation etc is fine. Somewhere deep, someone has changed value types.
I have a DataGrid bound to an ObservableCollection of DataRowView.
When I do any operations such as Insert/Delete/Copy/Paste/Undo/Redo, I manipulate the underlying DataSource.
Ex: When I have to paste data into a set of cells, I get their row and column indexes (the cell the context menu points to) and edit the DataSource. I store their previous values and their indexes to revert back when I do an "Undo" operation.
When I filter the grid, the view changes where as the DataSource remains the same. So, when I do a paste operation, the indexes I get don't match with the ones in the DataSource. I end up pasting in the wrong cells.
How can I manipulate the DataSource i.e get the actual indexes/data to do all the operations after filter is applied?
Based on what I understood after reading your question. New record which appear after Item1 should apppear after Item1 in source collection too. This is not happening right now as index is differing which will of course differ.
As you have not posted code, so I have posted sample code below :
// new employee to add
Employee empNew = new Employee() { Name = "New1", Address = "NewAdd1" };
// get corresponding item in filtered view after which you want to insert
Employee emp = (Employee)DgrdEmployees.SelectedItem;
// get true collection which is datasource
ObservableCollection<Employee> sourceCol = (ObservableCollection<Employee>)(CollectionViewSource.GetDefaultView(DgrdEmployees.ItemsSource).SourceCollection);
// find index of selected item after which we are inserting/pasting
int trueIndex = sourceCol.IndexOf(emp);
// insert it at exact location in true unfiltered source collection
sourceCol.Insert(trueIndex + 1, empNew);
I have this problem for days and can't find solution for it. I tried all possible solutions i found on internet, but seems like none suits this one.
Thing is that i added repository item to gridControls (i added it through designer, not through code). Then, in code i added data source to that repository lookUpEdit and i have items in dropDown in that column. But when i select item in repository and click on other cell, Selected item in repository is cleared and repository shows null value again...
Any ideas what i did wrong ?
EDIT:
Also, when i click on any cell in my grid, i have delay of second or two, and after that delay clicked cell is focused... Any solutions for all of this?
EDIT:
Don't know what code to show You, because I did all in devExpress designer. Here is part of the code where I set data source to repository item, and i will give You code from designer of that repository item.
private void ConfigureRepositoryItems()
{
BetService.SportManagerClient dbSportManager = new BetService.SportManagerClient();
BetService.BLOddsControlSettings[] oddsControlSettings = dbSportManager.GetOddsControlSettings("", "");
repositoryOddsControlSettings1.DataSource = oddsControlSettings;
}
And here is code from designer:
//
// repositoryOddsCalculationSettings1
//
this.repositoryOddsCalculationSettings1.AutoHeight = false;
this.repositoryOddsCalculationSettings1.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] {
new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)});
this.repositoryOddsCalculationSettings1.Columns.AddRange(new DevExpress.XtraEditors.Controls.LookUpColumnInfo[] {
new DevExpress.XtraEditors.Controls.LookUpColumnInfo("ID", "ID", 20, DevExpress.Utils.FormatType.None, "", false, DevExpress.Utils.HorzAlignment.Default),
new DevExpress.XtraEditors.Controls.LookUpColumnInfo("Name", "Name")});
this.repositoryOddsCalculationSettings1.DisplayMember = "Name";
this.repositoryOddsCalculationSettings1.Name = "repositoryOddsCalculationSettings1";
this.repositoryOddsCalculationSettings1.NullText = "Select Settings";
this.repositoryOddsCalculationSettings1.PopupSizeable = false;
this.repositoryOddsCalculationSettings1.ValueMember = "ID";
For starters check whether the column name in your Grid datasource and the column in your grid control match. The match is case sensitive so name and Name are not same and hence can cause this issue. Secondly make sure the Grid datasource column datatype matches the value type of the LookUpEdit. If the LookupEdit is returning int and the Grid datasource column datatype is string, this alone can cause lots of headaches.
I am able to apply NumberFormat on pivot fields using Microsoft.Office.Interop.Excel.PivotFields property. But that will not apply same format to summed fields. Is there any separate property for summed fields in pivot table that I am missing ?
Microsoft.Office.Interop.Excel.PivotFields pFields = pivotTable.PivotFields();
foreach (Microsoft.Office.Interop.Excel.PivotField pf in pFields)
if (pf.DataType == XlPivotFieldDataType.xlNumber)
pf.NumberFormat = "#,##0.00";
The documentation on these members isn't exactly crystal clear, but after a bit of digging around and trial and error it looks like the property you want is PivotTable.VisibleFields, which you need to cast to a PivotFields object to iterate through:
Excel.PivotFields vFields = (Excel.PivotFields)pivotTable.VisibleFields;
This will give you all visible fields in the table (as opposed to PivotTable.PivotFields() which only seems to give you the row labels column and the underlying source data). You might have to check the value of each one before you set the number format otherwise I believe it will apply it to everything in the table, which might not be what you want:
foreach (Excel.PivotField pf in vFields)
{
if (pf.DataType == Excel.XlPivotFieldDataType.xlNumber
& pf.Value == "Sum of Price")
{
pf.NumberFormat = "#,##0.00";
}
}
If you wanted to get to one cell in particular, then you can access the PivotField.PivotItems and iterate through those for each PivotField object:
Excel.PivotItems pi = (Excel.PivotItems)pf.PivotItems();
But I think most of the properties of PivotItem are read-only.