How to know if you're Dropping in the same app instance where you made the Drag in WPF? - wpf

the title pretty much explains my issue:
I am right now taking care of drag & drop in my app. I can have many instances of my app running at the same time, and I can drag from one instance to the other without trouble.
Now, I would like to know if I'm drag & dropping "internally" (i.e: the drop occurs in the same instance as the drag) or "externally" (the opposite)
I went this far: I need to add to my dragged data a unique ID (something like a PUID) that identifies the app where I'm making the drag. Then I can just compare this id to the one I have locally on the drop and see if it is the same.
I have no problem transferring such info in my drag Data, the issue is more to find this UId.
I have been thinking using the Process.GetCurrentProcess().MainWindowHandle; but I'm not sure if this is a good idea.
What option(s) do I have to make this work?

I would simply create a readonly Guid that gets set when you start your app.
You can put this wherever your main logic lives (MainWindow or ViewModel).
Here is a snippet:
public class MyViewModel
{
private readonly Guid mUID = Guid.NewGuid();
// In case you want a property for it
public string UniqueApplicationID
{
get { return mUID; }
}
public void OnDropHandler(MyViewModel objectBeingDropped)
{
if (objectBeingDropped.UniqueApplicationID == mUID)
return;
// Handle drop normally here
}
}

The D-n-D is much like an UI activity, than an internal one.
I would distinguish two contexts: dropping a file, and dropping some object (e.g. VS designer). In the first context there's no problem at all, because it doesn't matter where you pull the data. In the second case, you should know what object has been chosen. For instance, you have a listbox with many items (e.g. the alphabet chars), once the user D-n-D any of those items, the internal operation is a simple reference to the selected object. By pulling the data from another app, you won't be able to find your object, because the source is different.
In case of structs or strings, you may wrap them with a GUID, as you correctly proposed.

Related

Do Fluent conventions break lazy loading? (uNhAddIns)

I have a simple entity class in a WPF application that essentially looks like this:
public class Customer : MyBaseEntityClass
{
private IList<Order> _Orders;
public virtual IList<Order> Orders
{
get { return this._Orders; }
set {this._Orders = new ObservableCollection<Order>(value);}
}
}
I'm also using the Fluent automapper in an offline utility to create an NHibernate config file which is then loaded at runtime. This all works fine but there's an obvious performance hit due to the fact that I'm not passing the original collection back to NHibernate, so I'm trying to add a convention to get NHibernate to create the collection for me:
public class ObservableListConvention : ICollectionConvention
{
public void Apply(ICollectionInstance instance)
{
Type collectionType =
typeof(uNhAddIns.WPF.Collections.Types.ObservableListType<>)
.MakeGenericType(instance.ChildType);
instance.CollectionType(collectionType);
}
}
As you can see I'm using one of the uNhAddIns collections which I understand is supposed to provide support for both the convention and INotification changes, but for some reason doing this seems to break lazy-loading. If I load a custom record like this...
var result = this.Session.Get<Customer>(id);
...then the Orders field does get assigned an instance of type PersistentObservableGenericList but its EntityId and EntityName fields are null, and attempting to expand the orders results in the dreaded "illegal access to loading collection" message.
Can anyone tell me what I'm doing wrong and/or what I need to do to get this to work? Am I correct is assuming that the original proxy object (which normally contains the Customer ID needed to lazy-load the Orders member) is being replaced by the uNhAddIns collection item which isn't tracking the correct object?
UPDATE: I have created a test project demonstrating this issue, it doesn't reference the uNhAddins project directly but the collection classes have been added manually. It should be pretty straightforward how it works but basically it creates a database from the domain, adds a record with a child list and then tries to load it back into another session using the collection class as the implementation for the child list. An assert is thrown due to lazy-loading failing.
I FINALLY figured out the answer to this myself...the problem was due to my use of ObservableListType. In NHibernate semantics a list is an ordered collection of entities, if you want to use something for IList then you want an unordered collection i.e. a Bag.
The Eureka moment for me came after reading the answer to another StackOverflow question about this topic.

ZK window not unique in ID space

In our project we use ZK for webpages. There is a combobox which has lists. When selected, it fetches data from a java object through onSelect, i have given the logic.
when i select one there are 4 listboxes on that page to be filled with data according to the selection. when i select first time, no problem occurs.
But on second time i get an error pop-up like "Not Unique in the id space of Window" and showing the list box item id which have to be filled on select.
Can any one help out there?
Note: Though it shows this error i get the listboxes filled correctly according to the combo box selection. Still i cant stop this error occurring..
Your issue is a conflict of ids in ZK's id space.
A bit of background..
ZK generates ids for components at runtime, if you open up the DOM in the browser you'll see each component has some machine readable id.
However, you can also give components an id. This id does not go to the DOM but lets you reference the component in your application.
These two shouldn't be confused. The conflict you're experiencing is with the latter type of id; you are assigning a component an id in your Java code or in your ZUL file which, at runtime, is not unique.
The case you describe where it only happens the second time you click is a tell tale sign here. The content you are adding on the event has an id defined in it and you are not removing this content when you are done.
Consider the following example:
#Wire
private Window myWindow;
#Listen(Events.ON_CLICK + " = #myButton")
public void onMyButtonClicked() {
Label myLabel = new Label("sean is cool");
myLabel.setId("myLabel");
myLabel.setParent(myWindow);
}
This will work the first time you click myButton, but will throw your error on the second click. That is because the second event tries to add myLabel to myWindow but there is already a myLabel there.
There are lots of ways to resolve this depending on what you are trying to do.
Have a look through the ZK documentation on ID Spaces for more.
I also faced the same error.
My scenario is the same, only the widgets being used are different.
Hence putting my workaround here.
I have put the following piece of code in the doBeforeCompose() method of the composer:
Component widgetWithId = page.getFellowIfAny("widgetWithId");
if (widgetWithId != null) {
widgetWithId.detach();
}
Here widgetWithId is the component/widget, which is tried to be regenerated by the code, with the same Id and ZK is throwing error for it.

Using cached data from child window in parent window without a trip to the database

I'm looking for a design approach, so I don't have any code to share.
I have a WPF rich-client application that presents detail data to the user. When the user clicks "Edit" The entire form goes into edit state. This reveals a couple of "Add" buttons. These "Add" buttons open child views providing the user with tools to create new entities. Think "adding a new item to a customer order you're working with". That's the easy part.
When the user closes these child views, the new entities must be displayed and editable in the parent view for continued detailed editing. Something like "add the new item on the child form, pick the part number, then close the child and add quantity and delivery date on the parent view. I don't have any flexibility in this workflow. I have this working also.
When the user is finished with the parent view and is satisfied with the newly added items and detail edits they can click "Save". That is when all the changes need to go back to the database. If the user clicks cancel, all the changes including entities created on the child views must disappear, and the form returned to it's original state.
It's that last bit that stumps me. I'm almost new to Entity Framework, so I thought I could somehow keep the entire set of changes in memory on the client and commit all the changes to the database at the point of user-Save. I don't know if that's possible, or how I have to impliment my data changes to prevent accidental trips to the database.
To put all the facts on the table, I'm using a unit of work pattern, but I have access to an EF context object, if needed. If I have to work with the context object, I must do so across several views and their associated view-models.
I've looked at a whole lot of stackoverflow Q&A but cannot find, or perhaps recognize, a solution path. I've some ideas about using cloned entities, or perhaps transactions, but do not know if there are others or how to choose between them. These would be new skills and require time spent learning. I am willing to spend time learning a new skill, but not learning and trying three or four.
I'm grateful for any advice you might offer.
On the constructor when read from the DB record the value twice. One private variable for current and one for Old.
private string lNameOld;
private string lName;
public string LName
{
get { return lName; }
set
{
if(lName == value) return;
lName = value;
NotifyPropertyChanged("LName");
}
}
public void save()
{
if (lName != lNameOld)
{
// write to database
// really should process all in a transaction
lNameOld = lName;
}
{
public void cancel()
{
if (lName != lNameOld)
{
Lname = lNameOld; // notice capital L so Notify is called
}
{

Loading dropdownlists

what is the best way to load dropdown lists from reference/lookup tables for a desktop application?
the application is layed out into 3 tiers. I've built up my entities.
the front end has a form with 6 tabs. and one big save (another discussion :)
Should I load them all when the form is initially loaded? Are there any caching mechanisms I could use?
it is vb.net app on a network drive that is accessed by several users.
it's also worth noting that some reference tables may be updated. Via another form.
thanks
T
Lots of factors. One you need to populate in constructor so the data is there to populate the visual elements. Beware that just because a tab is not visible does not mean it is not loaded when you app starts.
For a static list of strings
public class Library : INotifyPropertyChanged
{
private List<string> dropDown1;
public List<string> DropDown1 { get { return dropDown1; } }
public Library()
{
// use data reader to populate dropDown1
}
}
I know this will get comments that can use something lighter than a List but List has a lot of nice features, easy syntax, and easy to populate. As a next step you could structure as a client server and use some static so the list is populated once and then shared by all. If you have more properties then substitute string with a class. For a dynamic list then in the get you grab the current data from the table on demand. In your get you could hold on to the last list and if the next request is within X seconds then return stale data. It depends on if stale data is acceptable.
There are many other approaches and I do not pretend this is the best. Just putting out a relatively simple example to get you started.
When it gets to hierarchical then things get a little more complex. There you can use ADO.NET table to store the static dependent data and then apply a filter on a view.
If its a web page you don't have to load all tabs on page load.
Desktop i think it will be more easy and it should be like that.
Only when the user click on the tab show the page and hide all the pages
associated for other tabs.
i hope all tab pages values will be on session so that user can go and come back to any tab and your Big Save at last.
Something useful related to your question i found here
http://www.syncfusion.com/FAQ/windowsforms/faq_c93c.aspx
and one more

Windows Phone 7: Tombstoning with URIs?

I'm building a wp7 app in Silverlight. All of my app's state is stored in NavigationContext.QueryString. If this could be saved on application deactivation, and that page navigated to on application reactivation, that would take care of my requirements for tombstoning.
However, I'm not quite sure how to do this. I was thinking about saving NavigationContext.QueryString to the State dictionary in App.xaml.cs::Application_Deactivated(), but that code doesn't have access to NavigationContext.QueryString. Is there another way I can do this?
I suppose I could just save the query string to the State dictionary every time I navigate, then restore that when the app is re-activated. Or is there a better approach?
Update: Based on indyfromoz's answer, I'd like to implement the following
OnNavigatedToHandler()
{
// save NavigationContext.QueryString in the State dictionary
}
To reduce redundancy, I thought I'd implement this in a class that inherits from PhoneApplicationPage, then have all the rest of my pages inherit from that class. However, I then get the problem that all the page classes are partial because they are also defined in generated code. I don't want to change the generated code, because rechanging it every time it gets regenerated would be a huge pain.
Is there a better way to do this?
Update 2: Here is what I am hacking together now in the main page of my app (the one that is navigated to on startup):
public partial class MainPivot : PhoneApplicationPage
{
public MainPivot()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainPivot_Loaded);
PhoneApplicationService.Current.Deactivated += new EventHandler<DeactivatedEventArgs>(App_Deactivated);
MessageBox.Show("launching main pivot (state count: " + PhoneApplicationService.Current.State.Count + ")");
if (PhoneApplicationService.Current.State.Count != 0)
{
Debug.Assert(PhoneApplicationService.Current.State.ContainsKey(QueryStringKey),
"State is initialized, but contains no value for the query string");
string oldQueryString = (string)PhoneApplicationService.Current.State[QueryStringKey];
MessageBox.Show("Old query string: " + oldQueryString);
NavigationService.Navigate(new Uri(oldQueryString));
}
}
public readonly string QueryStringKey = "queryString";
void App_Deactivated(object sender, DeactivatedEventArgs e)
{
PhoneApplicationService.Current.State[QueryStringKey] = NavigationService.Source;
}
// ...
It works (sorta) but it's ugly.
Update 3: Looks like the wp7 OS will automatically reload the correct page in a page-based app. I am in fact using pages, so perhaps there's not that much work I need to do here.
However, it doesn't seem to be working. I launch the app, go to a page, hit "Start", then hit "Back". The screen says "Resuming..." but seems to hang there. Is my code supposed to be responding in some way at this point? Is there a way I can keep the debugger attached even after hitting "Start"?
Transient data is usually stored in the State dictionary provided by the PhoneApplicationService class. The data is stored in the OnNavigatedFrom event of the page and restored from the OnNavigatedTo event of the page. If you stored the parameters from the URI of the page in the state dictionary within the OnNavigatedFrom event that is available in every page of your application, you can implement the logic to read the parameters in the OnNavigatedTo event, thereby taking care of Tombstoning
HTH, indyfromoz

Resources