Hi,
the GuessAutoFilterRowValuesFromFilter does not work correctly if the filter value is an referenced property. I have an column "Contact" - which is a referenced property to the contacts table. if i filter the column and filter is created like [Document.Contact]='MyContact' -> the right operand is the instance of the selected contact. If i call now GuessAutoFilterRowValuesFromFilter, the last line of this method if the problem i think:
column.FilterInfo = new ColumnFilterInfo(ColumnFilterType.AutoFilter, obj3, filterInfo.FilterString);
Here obj3 is correctly my contact instance - but this constructor takes the FilterString as parameter and converts the contact criteria to a string value, so [Document.Contact]='MyContact' -> MyContact is an string value now. So im wondering why dont you use CreateAutoFilterCriterion method instead filterInfo.FilterString or even the CreateFilterRowInfo() method?
GuessAutoFilterRowValuesFromFilter does not work with referenced values
Answers
Hi Martin,
The GuessAutoFilterRowValuesFromFilter method is implemented in this way, because it was created to implement a feature requested in the Display the filter in the AutoFilterRow after the view's layout has been restored suggestion. We don't want to break the functionality of existing applications when this feature is introduced, and we want to avoid involving the redundant XtraGrid functionality in this process. This method isn't used for other purposes in our code, and is marked as internal in the documentation: GridView.GuessAutoFilterRowValuesFromFilter Method. We don't consider this implementation incorrect.
>> what if i only work with XtraGrid and build my own way to store the criteria
The XtraGrid doesn't provide methods to restore values in the Auto Filter Row from the ActiveFilterCriteria. Even the GuessAutoFilterRowValuesFromFilter doesn't work impeccable in all situations. That is why this feature is still not supported officially.
Besides the Auto Filter Row, the GridView supports other scenarios of applying the filter. A column filter can be applied via the column's filter drop-down list. In addition, a more complex filter can be applied via the built-in Filter Editor, or via an external FilterControl. The ActiveFilterCriteria can be modified in code. A correct way to restore values in the Auto Filter Row is to save the ColumnFilterInfo of GridColumns, rather that the GridView.ActiveFilterCriteria property.
Thanks,
Uriah.
Hello Martin,
I'm afraid that the problem your are experiencing is not quite clear to me. First of all, I must say that the GuessAutoFilterRowValuesFromFilter method is not supposed to be used directly in your code. This method is created for internal use only. Could you please clarify the problem you are currently experiencing in greater detail. Please attach a sample demonstrating the problem describe the expected results in all possible details.
Thanks,
Stan.
Hi Stan,
"First of all, I must say that the GuessAutoFilterRowValuesFromFilter method is not supposed to be used directly in your code. This method is created for internal use only" -> i was pointed to this method and there is also an official example for it… -> E1759
To reproduce, take the XAF MainDemo - modify the GridFormattingController in Module.Win. Set the TargetObjectType to Contact, and in the View_ControlsCreated call the GuessAutoFilterRowValuesFromFilter Method. Enable the AutofilterRow for the Contact_ListView. Now start the App - filter the Contact via the Position column. If you have set the Filter click 2! times the Contact item in the Navigation bar - after the second click you will see that the filter is no longer visible, and if you click into the filter column you get an invalidcastexception because the value is now an string…?
Hi Martin,
We've managed to reproduce this problem. We'll research it and will provide you with a solution as soon as possible.
Thanks,
Uriah.
Hi Martin,
Thank you for your report. The cause of the problem is that persistent objects can't be serialized. Thus, the ActiveFiterCriteria, containing a reference to a persistent object can't be serialized, either. That is why this approach won't work for a look-up column bound to the reference property. To resolve this problem, bind the look-up column to the object's key, rather than to the object itself.
colContact.FieldName = "Contact!Key"; contactLookup.DataSource = contacts; contactLookup.ValueMember = "Oid"; contactLookup.DisplayMember = "Name";
However, it appears that in XAF application this behavior causes another problem. We've cloned this issue to another bug report, and passed it to the XAF team. You can track its state at the GridListEditor.Filtering - Make it possible to restore values in the auto filter row.
Thanks,
Uriah.
Hi Uriah,
"Thus, the ActiveFiterCriteria, containing a reference to a persistent object can't be serialized, either" -> thats not true - in XAF the ActiveFiterCriteria is persistet in the Model - so as i sayed "obj3" is the correct instance of the referenced property. So why dont you use the CreateFilterRowInfo(GridColumn column, object _value) method or at least the CreateFilterRowInfo(GridColumn column, object _value) Method?
Hi Martin,
Yes, both the XAF application and the standalone GridView can persist criteria containing a reference to a persistent object. However it doesn't make sense, because there is no way to restore the original value. For example, when modifying the main demo in a way you described, I received the following record in the Model.User.xafml file:
<ListView ID="Contact_ListView" ActiveFilterString="[Position!] = 'Manager'">
It's obvious that this information isn't enough to restore a reference to a persistent object. At the very least, it's necessary to know the object's key. That is why I said that the CriteriaOperator containing a reference to the persistent object couldn't be serialized.
Thanks,
Uriah.
Hi Uriah,
"<ListView ID="Contact_ListView" ActiveFilterString="[Position!] = 'Manager'">" -> thats right - but XAF has the FilterWithObjectsProcessor which converts this back to the original criteria. At all i dont understand why this issue is related with serialization? As you see XAF restores the Grid ActiveFilterCriteria, thus all Columns have the correct filterinfos. But, if you call GuessAutoFilterRowValuesFromFilter the criteria is destroyed and thats not logical…?
BTW: This is what XAF actually stores in the Model:
"[Address.City!] = '@ObjectType:VenDoc.Persistent.BaseImpl.City@ObjectID:3dabe784-020f-462f-90f3-ab2c98cea093'"
Hi Martin,
Sorry, it was my mistake. I suppose that in my situation the ActiveFilterserCriteria is serialized incorrectly because of an internal error. I've discussed the problem with the XAF developers, and they confirmed that XAF uses own serialization mechanism, and can properly restore references.
The XtraGrid serializes ActiveFilterCriteria in a different manner, because it is intended to support data sources of various types, and knows nothing about XPO. I believe that this problem is related on XAF, and will be resolved in the context of the GridListEditor.Filtering - Make it possible to restore values in the auto filter row bug report. If you want to append any additional information regarding this problem, please feel free to write here, and I'll add your comments to this bug report. Also, you can write in the "Discussion" section of the mentioned bug report, as well.
BTW: I apologize for the inconvenience caused by separating this report into different issues. In fact, this report applies to both XtraGrid and XAF. That is why we decided to process these issues separately.
Thanks,
Uriah.
Hi Uriah,
no problem. But i still dont understand why this issue is related to serialization? The GuessAutoFilterRowValuesFromFilter just restores the Values from an EXISTING FilterInfo. Can you explain why for example not this costructor is used:
ColumnFilterInfo(ColumnFilterType type, object _value, CriteriaOperator filter, string displayText) -> this way the criteria would not get destroyed by the CriteriaOperator.TryParse… ?
Hi Martin,
The problem is related to the serialization, because the GridView restores the ActiveFilterString from the layout. So, after deserialization, the ActiveFilterString is changed and update the ActiveFilterCriteria. The GridView doesn't perform any complex operations to restore the filter from the string. It uses the CriteriaOperator.TryParse method. This method can't resolve references to an object, and treats them as a string values: Limitations of CriteriaOperator.Parse.
So, this code can't properly restore values in the Auto Filter Row, if these values are references to an object:
gridView1.RestoreLayoutFromXml(@"..\..\layout.xml"); gridView1.GuessAutoFilterRowValuesFromFilter();
But this code properly set the filter, and puts a correct value in the corresponding cell in the Auto Filter Row:
gridView1.ActiveFilterCriteria = new BinaryOperator("CategoryID!", gridView1.GetRowCellValue(1, gridColumn1)); gridView1.GuessAutoFilterRowValuesFromFilter();
If the GridView.OptionsLayout.StoreDataSettings property is set to false, the ActiveFilterString won't be changed after deserialization. However, in this situation it's impossible to restore the previous filter, if it was modified, or the application was restarted.
Thanks,
Uriah.
Hi Uriah,
sorry if i bother you. This is exactly what we do in XAF: XAF restores the ActiveFilterCriteria with all references, and afterwards we call GuessAutoFilterRowValuesFromFilter - so i ask again why in this case the Filter gets corrupted?
gridView1.ActiveFilterCriteria = new BinaryOperator("CategoryID!", gridView1.GetRowCellValue(1, gridColumn1));
gridView1.GuessAutoFilterRowValuesFromFilter();
Hi Martin,
You are right, for some reason this scenario doesn't work in XAF applications, while in the XtraGrid it works fine. I have to agree with you that the GuessAutoFilterRowValuesFromFilter method should (or, to be more precise, can) correctly restore the filter criteria in any case. I've asked our developers why this method is implemented in this manner. In fact, this method is intended only to restore the Auto Filter after restoring the layout, and shouldn't be used for other tasks (for example, populate the AutoFilterRow, after applying ActiveFilterCriteria). So, we can't consider the current implementation to be incorrect, because this method works correctly in the scenario it meant to be used. I've modified the Subject of the How to restore the Auto Filter Row from the ActiveFilterString, after restoring the layout, because the previous subject has a slightly incorrect meaning.
Thanks,
Uriah.
Hi Uriah,
i try it the last time. This issue is not related to XAF - what if i only work with XtraGrid and build my own way to store the criteria.
You have also changed the Subject of the example now wich is wrong in my opinion. The Methods Name is GuessAutoFilterRowValuesFromFilter -> it has nothing todo with restoring the layout - i can call this method also if i build the columns/layout in my own way. So can you please cleary explain why you dont use this constructor:
ColumnFilterInfo(ColumnFilterType type, object _value, CriteriaOperator filter, string displayText)