Semantic Zoom Catastrophic failure on empty group - windows-8

I am using the SemanticZoom control with a grid view and collection view source. All is working fine until I attempt to select ('jump to') an empty group - this causes an unhandled Catastrophic failure.
http://social.msdn.microsoft.com/Forums/nb-NO/winappswithcsharp/thread/6535656e-3293-4e0d-93b5-453864b95601
Does anybody know if there is a way to fix this - I want to 'allow' an empty group if I can.
Thanks

Okay, so I ran into this issue and fixed it. I know this is quite an old thread, but I'll answer it in case someone else runs into this. Here's how I did it.
The issue seems to be that the group set as the DestinationItem needs to have items in it. In the case that this group is empty, this poses a problem. The problem does not occur when the group is in between other filled groups, because it has a length of 0 and therefore is untargetable. When it is at the end (or possibly the beginning, haven't tried that), this poses an issue because the GridView/ListView targets the last one in the list when the mouse is past the end of the view.
So, how to solve it:
You need to add an event handler for OnViewChangeStarted. In this handler, you will have access to the SemanticZoomViewChangedEventArgs.
The first thing you need to do is find out if the Group being targetted is empty. I am using a custom Group class here, but have cast it to IEnumerable, just because I only need to know how many items are in it. Linq allows me to find the count of the IEnumerable.
using System.Linq;
private void Zoom_OnViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e)
{
var group = e.DestinationItem.Item as IEnumerable;
if (group != null && group.Count() == 0)
{
e.DestinationItem.Item = MyViewModel.Groups.Last(itemGroup => itemGroup.Count() > 0);
}
}
As you'll note, the next step is to set the DestinationItem.Item to the Last group that has items in it. You may also want to handle the First group that has items in it, but that's quite easy to do as well. In place of MyViewModel, insert your ViewModel. In place of Groups, insert your collection property.
I hope this helps and happy coding!

Related

Filter parent data source with a field which is in another table in D365

Some times we need to filter a form grid based on the status of the transaction reference Id. Assume that we want to show purchase orders with confirm document state in arrival overview form. The document state field is located in the purch table. For this aim, I try to outer join WMSArrivalOverviewTmp to purch table and add Range. However the results is not as I expect.
This is the code I have tried in the initialized data source event:
[FormDataSourceEventHandler(formDataSourceStr(WMSArrivalOverview, WMSArrivalOverviewTmp), FormDataSourceEventType::Initialized)]
public static void WMSArrivalOverviewTmp_OnInitialized(FormDataSource sender, FormDataSourceEventArgs e)
{
QueryBuildDataSource qbds = sender.queryBuildDataSource();
QueryBuildDataSource qbdsPO;
qbdsPO = qbds.addDataSource(tableNum(PurchTable));
qbdsPO.clearRange(fieldNum(PurchTable, DocumentState));
qbdsPO.joinMode(JoinMode::OuterJoin);
qbdsPO.fetchMode(QueryFetchMode::One2One);
qbdsPO.addLink(fieldNum(WMSArrivalOverviewTmp, InventTransRefId ),fieldNum(PurchTable, PurchId), qbds.name());
qbdsPO.relations(false);
qbdsPO.addRange(fieldNum(PurchTable, DocumentState)).value(SysQuery::value(VersioningDocumentState::Confirmed));
info(sender.query().toString());
}
This is the query which has been shown :
SELECT FIRSTFAST * FROM WMSArrivalOverviewTmp(WMSArrivalOverviewTmp)
OUTER JOIN FROM PurchTable(PurchTable_1) ON
WMSArrivalOverviewTmp.InventTransRefId = PurchTable.PurchId AND
((DocumentState = 40))
Also, I have changed the event type to query executing but I get errors:
[Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Error converting
data type nvarchar to bigint.
Cannot select a record in Purchase orders (PurchTable). The SQL
database has issued an error.
P.S. I have noticed that the error comes when I click on the update button after I fill one of the field in the filter section(arrival option). For example when I fill account number or warehouse. And also I have noticed that when I click on the update button while the fields are not filled in the filter section the join operation has not applied correctly, i.e., the purchase orders which have draft status are shown.
Your actual query looks correct to me. I would add that you may want to add the link between the WMSArrivalOverviewTmp.InventTransType == InventTransType::Purch (or set qbds.relations(true) so that you use the table's built in relation), but I doubt that is the root of your problem. Of course it wouldn't hurt to make sure your query works in the manner that you expect it to by converting the results of the info() call you have into SQL code and run it in SSMS to double check the result set.
Also, I'm curious why would you put the event on the datasource you are trying to manipulate? I would recommend investigating to see if it can occur on the OnModified event of the "status of the transaction reference Id". Although perhaps I am misunderstanding - if this situation is more of a "we need to happen all the time when the form loads" than a "some times we need" as you start your question off - the place to change the query is to modify it in a handler of the datasource's OnQueryExecuting event.
There are two ways of modifying the query on an event when an event occurs.
FormRun formRun = sender.formRun() as FormRun;
FormDataSource formDataSource = formRun.dataSource(formDataSourceStr(WMSArrivalOverview, WMSArrivalOverviewTmp));
//First way - get the base query and use executeQuery() to reload changes
Query query = formDataSource.query();
//modified query here.
formDataSource.executeQuery();
//Second way - get the current queryRun query and use research() to reload changes
Query query = formDataSource.queryRun.query();
//modified query here.
formDataSource.research();

Retrieve a document class-description symbolicName without fetching

I'm triying to retrieve a ClassDescription symbolicName of an IDocument object. It seems that i have to fetch its ClassDescription even if I just want the symbolicName.
Is there a way to do it ? I just want to avoid doing a fetch for every browsed document...
(Also IDocument.GetClassName doesn't help, it returns "Document")
I finally found a way, by making an SQL SELECT request retrieving the classDescription ID (which is not the symbolicName ID, but rather an "internal" one) :
Select This, d.Id, d.ClassDescription
From Document d
where d.Id = ID
It seems to be lighter than a line like document.fetch(classDescription) (pseudo call) cause it should just retrieves the ID.
I thought it worth mentioning a problem regarding the accepted answer.
There are times that doing a query would be "lighter" however I believe you are missing something involving fetching a document.
FileNet's fetchInstance command can take in a PropertyFilter.
In your case you could do something along the lines of:
PropertyFilter pf = new PropertyFilter();
pf.AddIncludeProperty(new FilterElement(null, null, null, "ClassDescription", null));
doc = Factory.Document.FetchInstance(os, new Id("doc.ID()"), pf);
You would probably want to look at your original fetch of this document and make sure to specify the full list of property filters at that point.
See Working With Documents

How to remove from one list all the items in another?

I'm reading a set of rows from a remote database, and a similar set from a local database, and then using RemoveAll to get rid of remote rows that are already present locally...
remote_events = (From a In remote.Events
Where ...etc...).ToList
local_events = (From a In local.Events
Where ...etc...).ToList
remote_events.RemoveAll(Function (ByVal event_row As Remote_Event)
(From a In local_events Where a.Identifier = event_row.Identifier).Count > 0)
but this doesn't seem right to me. I don't think I should be counting things when all I really need to do is check whether a match exists. I've tried various usages of IsDBNull and IsNothing but get nonsense. I can't use .Except (as suggested here) because the list elements are not the same type.
Is there a better way of doing this?
One way is this:
remote_events.RemoveAll(Function(e) local_events.Exists(Function(f) f.Identifier = e.Identifier))
I'm trying to do this without visual studio, so I'm not sure if this will work, but I'd suppose you could do something along these lines if what you're trying to do is compare the Identifier:
Remote_Events = (From r_evt In Remote_Events
Where Not ((From l_evt In Local_Events Select l_evt.Identifier).Contains(r_evt.Identifier))
Select r_evt).ToList
I hope this helps and at least moves you in the right direction.

How do I use Linq-to-sql to iterate db records?

I asked on SO a few days ago what was the simplest quickest way to build a wrapper around a recently completed database. I took the advice and used sqlmetal to build linq classes around my database design.
Now I am having two problems. One, I don't know LINQ. And, two, I have been shocked to realize how hard it is to learn. I have a book on LINQ (Linq In Action by Manning) and it has helped some but at the end of the day it is going to take me a couple of weeks to get traction and I need to make some progress on my project today.
So, I am looking for some help getting started.
Click HERE To see my simple database schema.
Click HERE to see the vb class that was generated for the schema.
My needs are simple. I have a console app. The main table is the SupplyModel table. Most of the other tables are child tables of the SupplyModel table.
I want to iterate through each of Supply Model records. I want to grab the data for a supply model and then DoStuff with the data. And I also need to iterate through the child records, for each supply model, for example the NumberedInventories and DoStuff with that as well.
I need help doing this in VB rather than C# if possible. I am not looking for the whole solution...if you can supply a couple of code-snippets to get me on my way that would be great.
Thanks for your help.
EDIT
For the record I have already written the following code...
Dim _dataContext As DataContext = New DataContext(ConnectionStrings("SupplyModelDB").ConnectionString)
Dim SMs As Table(Of Data.SupplyModels) = _dataContext.GetTable(Of Data.SupplyModels)()
Dim query = From sm In SMs Where sm.SupplyModelID = 1 Select sm
This code is working...I have a query object and I can use ObjectDumper to enumerate and dump the data...but I still can't figure it out...because ObjectDumper uses reflection and other language constructs I don't get. It DOES enumerate both the parent and child data just like I want (when level=2).
PLEASE HELP...I'M stuck. Help!
Seth
in C# it would be:
var result = from s in _dataContent.SupplyModels where s.SupplyModelID==1 select s;
foreach(SupplyModel item in result)
{
// do stuff
foreach(SupplyModelChild child in item.SupplyModelChilds)
{
//do more stuff on the child
}
}
and a VB.NET version (from the Telerik code converter)
Dim result As var = From s In _dataContent.SupplyModels _
Where s.SupplyModelID = 1 _
Select s
For Each item As SupplyModel In result
' do stuff
'do more stuff on the child
For Each child As SupplyModelChild In item.SupplyModelChilds
Next
Next

jqGrid/NHibernate/SQL: navigate to selected record

I use jqGrid to display data which is retrieved using NHibernate. jqGrid does paging for me, I just tell NHibernate to get "count" rows starting from "n".
Also, I would like to highlight specific record. For example, in list of employees I'd like a specific employee (id) to be shown and pre-selected in table.
The problem is that this employee may be on non-current page. E.g. I display 20 rows from 0, but "highlighted" employee is #25 and is on second page.
It is possible to pass initial page to jqGrid, so, if I somehow use NHibernate to find what page the "highlighted" employee is on, it will just navigate to that page and then I'll use .setSelection(id) method of jqGrid.
So, the problem is narrowed down to this one: given specific search query like the one below, how do I tell NHibernate to calculate the page where the "highlighted" employee is?
A sample query (simplified):
var query = Session.CreateCriteria<T>();
foreach (var sr in request.SearchFields)
query = query.Add(Expression.Like(sr.Key, "%" + sr.Value + "%"));
query.SetFirstResult((request.Page - 1) * request.Rows)
query.SetMaxResults(request.Rows)
Here, I need to alter (calculate) request.Page so that it points to the page where request.SelectedId is.
Also, one interesting thing is, if sort order is not defined, will I get the same results when I run the search query twice? I'd say that SQL Server may optimize query because order is not defined... in which case I'll only get predictable result if I pull ALL query data once, and then will programmatically in C# slice the specified portion of query results - so that no second query occur. But it will be much slower, of course.
Or, is there another way?
Pretty sure you'd have to figure out the page with another query. This would surely require you to define the column to order by. You'll need to get the order by and restriction working together to count the rows before that particular id. Once you have the number of rows before your id, you can figure what page you need to select and perform the usual paging query.
OK, so currently I do this:
var iquery = GetPagedCriteria<T>(request, true)
.SetProjection(Projections.Property("Id"));
var ids = iquery.List<Guid>();
var index = ids.IndexOf(new Guid(request.SelectedId));
if (index >= 0)
request.Page = index / request.Rows + 1;
and in jqGrid setup options
url: "${Url.Href<MyController>(c => c.JsonIndex(null))}?_SelectedId=${Id}",
// remove _SelectedId from url once loaded because we only need to find its page once
gridComplete: function() {
$("#grid").setGridParam({url: "${Url.Href<MyController>(c => c.JsonIndex(null))}"});
},
loadComplete: function() {
$("#grid").setSelection("${Id}");
}
That is, in request I lookup for index of id and set page if found (jqGrid even understands to display the appropriate page number in the pager because I return the page number to in in json data). In grid setup, I setup url to include the lookup id first, but after grid is loaded I remove it from url so that prev/next buttons work. However I always try to highlight the selected id in the grid.
And of course I always use sorting or the method won't work.
One problem still exists is that I pull all ids from db which is a bit of performance hit. If someone can tell how to find index of the id in the filtered/sorted query I'd accept the answer (since that's the real problem); if no then I'll accept my own answer ;-)
UPDATE: hm, if I sort by id initially I'll be able to use the technique like "SELECT COUNT(*) ... WHERE id < selectedid". This will eliminate the "pull ids" problem... but I'd like to sort by name initially, anyway.
UPDATE: after implemented, I've found a neat side-effect of this technique... when sorting, the active/selected item is preserved ;-) This works if _SelectedId is reset only when page is changed, not when grid is loaded.
UPDATE: here's sources that include the above technique: http://sprokhorenko.blogspot.com/2010/01/jqgrid-mvc-new-version-sources.html