Why is DragDrop not working under VS2010? - winforms

I have a winforms app that uses a UserControl. The user control's job is to collect a file that the user drops on it from Windows Explorer, Open the file, determine the type and handle it accordingly.
This control worked PERFECTLY under Visual Studio 2008 Pro. I upgraded to VS 2010 Pro, and now, it doesn't work. Is there a flag or a property that has changed that I should be aware of??
I made a quick demo to test. This demo works perfectly under 2008, but doesn't work at all under 2010.
The setup: Create a new winform project. Add a user control. Set the following code in the user control's code section. (compile to get the user control to appear in the toolbox) Add the user control to the form. Run the program, and drag ANY file from windows onto the form. If it works, the user control area should change colors.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.AllowDrop = true;
this.DragDrop += new DragEventHandler(UserControl1_DragDrop);
this.DragEnter += new DragEventHandler(UserControl1_DragEnter);
this.DragLeave += new EventHandler(UserControl1_DragLeave);
}
void UserControl1_DragLeave(object sender, EventArgs e)
{
this.BackColor = Color.FromName("Control");
}
void UserControl1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
this.BackColor = Color.Blue;
}
else
{
e.Effect = DragDropEffects.None;
}
}
void UserControl1_DragDrop(object sender, DragEventArgs e)
{
this.BackColor = Color.Yellow;
}
}
I'm open to any explanation or fix that you guys may think up!
UPDATE:
I tested using the comments listed below. STILL doesn't work. However, I have noted that it only fails while in the development environment. When I go to the bin directory and launch the program manually, it works fine. It just doesn't work when I am in the development environment, which makes debugging a bit difficult. Still looking for the big-picture fix.

A likely failure cause here is UIPI, the user interface component of UAC. You cannot drag from a non-elevated process and drop to a window owned by an elevated process. You'll trigger this when you started Visual Studio from a shortcut that has the "Run this program as an administrator" option in the Compatibility tab turned on. The only workaround is to turn that option off. Or to run it directly from the .exe file, as you discovered.

Related

windows 8.1 assigned access for Desktop App

I have a Desktop Application written in WPF (originally for Windows 7) that I would like to run in Kiosk (Assign Access mode) on a Microsoft Surface Pro 2. The assigned access feature looked perfect, but it doesn't support non-store apps.
I just need a way to prevent the user from switching to another app or getting access to the OS etc.
Possible?
Make your application fullscreen as shown here: full screen wpf
In your main window constructor subscribe on Deactivate event or override OnDeactivate method:
Deactivated += delegate(object sender, EventArgs e) {
Activate();
};
You would also want to prevent the window from Alt+F4 closing by handling the Closing event on such a way:
Closing += delegate(object sender, CancelEventArgs e)
{
if(!Environment.HasShutdownStarted)
e.Cancel = true;
};
After all done, the application is closable only by task manager, sign out and shutdown.

ALT-TAB always activates main window in WPF app with multiple owned windows

On Windows 7, .NET 4.0 I have a problem that can be reproduced by copying the following code into a blank WPF application generated by Visual Studio:
public MainWindow()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
new Window() { Title = "Test", ShowInTaskbar = false, Owner = this }.Show();
}
Run app
Activate secondary window
Alt-Tab to other running application
Use mouse to activate our WPF app in taskbar
Now the WPF app is active again, with the secondary window activated and the main window deactivated, which is the expected (and desired) behavior.
Now do this instead (only step 4 differs):
Run app
Activate secondary window
Alt-Tab to other running application
Alt-Tab back to our WPF app
The WPF app is active again, but now the main window is activated.
Adding this code
private void Application_Activated(object sender, EventArgs e)
{
Windows[1].Activate();
}
to App.xaml.cs does not solve the problem because now in the second case both windows are activated. Also, clicking the secondary window does not deactivate the main window. I have to click the (already activated) main window and the secondary window again to achieve this.
How can I avoid this (only the secondary window should be active in both cases)?
CodeProject actually addresses this issue here, hope this is what you're looking for.
Combine with a post from Tamil Khason and in theory you can override the OnFocus event on a global level so that every time a window is on focus, that becomes the "main window" which will then be the target of ALT+TAB.
based on THIS solution the following code can maybe (not tested jet) also do the trick
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent, new RoutedEventHandler(WindowLoaded));
base.OnStartup(e);
}
void WindowLoaded(object sender, RoutedEventArgs e)
{
Window w = sender as Window;
if (w != null)
{
// this part works in my case very well
w.Owner =Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
}
}

How do I simulate Visual Studio application window activation?

I'm trying to do something similar to what visual studio does with it's windows. I have a similar tabbed interface and I have added the ability to undock a tab into a separate window. The functionality I'm trying to get is where a user activates one of the windows of the application, all of the application windows should be brought to the top. My first thought was to override the OnActivated Window method where I would activate all of the other application windows. However, this is insufficient because that ends up bringing all of the other windows on top of the window I just activated (since OnActivated is called after the window is activated). I can't activate it last in this event because that would fire the activated event again (infinite loop). It would be nice if there was an OnActivating event that was call before the window was activated.
Has anyone else done this?
This doesn't work because it brings the other windows on top of the one just activated.
public partial class EditorWindow : Window
{
public event EventHandler ActivateOtherWindows;
protected override void OnActivated(EventArgs e)
{
if(ActivateOtherWindows != null)
{
ActivateOtherWindows(this, EventArgs.Empty);
}
base.OnActivated(e);
}
}

Appropriate point to attach NodeChanged event, XAML

I've got a WPF usercontrol in a winforms application form.
Basically, I want a generic eventhandler attached to my WPF TreeView to handle "Document.NodeChanged". As this particular event fires when the tree is populated, I attempted to do a late attachment, via my treeview control's Loaded event.
The code goes something like:
private void UpdateGrid()
{
myGridView.UpdateXML(entityId, runDate, rtbToggleFullView.ToggleState == Telerik.WinControls.Enumerations.ToggleState.Off, userName);
//Safely attach the event to fire when the treeview has finished loading.
myGridView.tvRatings.Loaded -= AttachNodeChangedEvent;
myGridView.tvRatings.Loaded += AttachNodeChangedEvent;
}
Then the "AttachNodeChangedEvent" method looks like this:
public void AttachNodeChangedEvent(object i, EventArgs a)
{
((XmlDataProvider)myGridView.dataProvider).Document.NodeChanged -= OnNodeChanged;
((XmlDataProvider)myGridView.dataProvider).Document.NodeChanged += OnNodeChanged;
}
With a simple OnNodeChanged method:
public void OnNodeChanged(object i, EventArgs a)
{
Dirty = true;
}
The idea being:-
UpdateGrid runs UpdatesXML on treeview
Attaches a "NodeChangeHandler attacher" to treeview.Loaded
(when treeview is loaded) treeview fires "NodeChangeHandler attacher" which then attaches "OnNodeChanged" to the Treeview's populated XmlDocumentProvider.
This appeared to work perfectly in Windows 7. In Windows XP, however, the AttachNodeChangedEvent routine fires, and experiences a NullReferenceException (presumably because the Document hasn't loaded yet?) crashing the app.
Commenting out the ...((XmlDataProvider)myGridView... lines fixes the crash, but obviously disables the functionality.
Can anyone suggest a better way of achieving the same, or shed some light on why this works for Windows 7, but not Windows XP? "e.g. Attach NodeChangedEvent after the initial population of the Treeview"
I can confirm that both use the appropriate .Net Framework 4 package and seem to have all other dependencies appropriately included.
Thanks!

WPF ComboBox DropDown part appears in the wrong place

I put several ComboBoxes on a XAML window. When I expand any of them, the DropDown part appears on the upper left corner of the screen.
I use Visual Studio 2008 C# Express. I don't remember this phenomenon when I used Visual Studio 2008 (Trial Version), though I use the same FrameWork (3.5).
It seems to be a bug.
Workaround:
Use Window.Show() instead with a custom logic to simulate the ShowDialog() behavior.
This appears to be a bug in WPF. In my case, I was trying to open a window in the Loaded event of another window. To get around this, I set a timer up to fire, then used a delegate to open the window (cannot open the window in a timer event because the calling thread that opens a window must be STA).
Edit - timer isn't necessary - didn't see the answer above just queue it on the dispatcher...
private delegate void DelegateOpenWindow();
private DelegateOpenWindow m_DelegateOpenWindow;
private Timer loginTimer = new Timer(200);
private void MainWindow1_Loaded(object sender, RoutedEventArgs e)
{
// create delegate used for asynchronous call
m_DelegateOpenWindow= new DelegateOpenWindow(this.OpenWindow);
// start a timer to fire off the open window.
loginTimer.Elapsed += loginTimer_Elapsed;
loginTimer.Enabled = true;
}
void loginTimer_Elapsed(object sender, ElapsedEventArgs e)
{
loginTimer.Enabled = false;
this.Dispatcher.BeginInvoke(m_DelegateOpenWindow);
}
void OpenWindow()
{
MyWindow w = new MyWindow();
w.Owner = this;
w.ShowDialog();
}
I started observing this (and other strange behavioral quirks) yesterday when I tried to "tweak" window sizes, shapes, colors, and invoke a log-on dialog from the Window.Loaded event handler. I had been doing this just fine in each of a dozen+ individual "MVVM" pattern apps. Yesterday, I decided to move this from each app's code behind into a consolidated code-behind base class, since the pre-processing had become common in all those apps. When I did, the drop-downs in two ComboBoxes in the log-in dialog suddenly appeared in the upper left corner of my screen. I seem to have "solved" it by using the following technique (your mileage may vary):
protected void WindowBaseLoadedHandler(object sender, RoutedEventArgs e)
{
...non-essential lines of code removed...
if (DataContext != null)
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
/*----------------------------------------------------------------------
* Do we have a View Model? If so, perform standard VM Initialization...
*---------------------------------------------------------------------*/
this.IsEnabled = false;
LoginDlg loginDlg = new LoginDlg();
loginDlg.ShowDialog();
if (!loginDlg.Success)
{
/*-----------------------------------
* Log on failed -- terminate app...
*----------------------------------*/
...termination logic removed...
}
this.IsEnabled = true;
}));
}
WindowBaseLoadedHandler is the Loaded event handler. LoginDlg is a WPF app with a dialog containing two ComboBoxes.
Recap: After I consolidated the code into the Loaded event handler of the base class the ComboBox's drop down lists appeared in the upper left corner of my screen. Once I wrapped the logic into the Dispatcher.BeginInvoke call, the appropriate ComboBox behavior returned with lists below the current item.
I suspect WPF needs the application to return from the Loaded event to complete the layout system's initialization. That doesn't fully explain why it worked before, but I'll have to queue up my desire to hunt that "why" down for some rainy day in the future and celebrate overcoming the latest obstacle for today.
In any event, I hope someone finds this of use.
I'm using the latest .Net 4.5 and WPF framework and I still have this problem. One thing I noticed is that it only happen when there's an attached debugger. When the debugger is not attached, everything works fine.
I had the same problem on Visual Studio 2019.
Using window.Show() can help but it can ruin your design.
The solution is to open the window asynchronously.
var yourDialog= new YourDialog();
yourDialog.Owner = this;
TaskCompletionSource<bool?> completion = new TaskCompletionSource<bool?>();
this.Dispatcher.BeginInvoke(new Action(() =>
completion.SetResult(yourDialog.ShowDialog())));
bool? result = await completion.Task;
You can also create a more elegant solution by making the extension method:
public static class AsyncWindowExtension
{
public static Task<bool?> ShowDialogAsync(this Window self)
{
if (self == null) throw new ArgumentNullException("self");
TaskCompletionSource<bool?> completion = new TaskCompletionSource<bool?>();
self.Dispatcher.BeginInvoke(new Action(() => completion.SetResult(self.ShowDialog())));
return completion.Task;
}
}
And you can use it like this:
await dlgReview.ShowDialogAsync();
It’s a bug in WPF (not the only one, I'm afraid). It happened when I opened another window in the Loaded Event, something like:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Window selectionWindow = new SelectionWindow();
bool? result = selectionWindow.ShowDialog();
if (result == true)
RecordChanged();
}
I already found a workabout.

Resources