InvalidOperationException thrown while trying to open new Window - wpf

I have this WPF application in which MainNavigationWindow has registerd events of some other class in its Constructor:
SomeClass obj = new SomeClass();
obj.SomeEvent += new EventHandler(SomeEventHandler);
In the EventHandler method I am trying to show another window, like:
SomeWindow window = new SomeWindow();
window.ShowDialog();
But while creating the new object the above exception is thrown. Can anybody please tell me what can the possible problem and how can I resolve it?
Please note that SomeWindow is derived from System.Window only.

It sounds like the event isn't being raised in the UI thread, and you need to marshal over to the UI thread before creating the window. This is probably as simple as changing your event handler code to:
Action action = () => {
SomeWindow window = new SomeWindow();
window.ShowDialog();
};
Dispatcher.BeginInvoke(action);

Related

Dispatcher.BeginInvoke is not triggering in WPF

I am new to WPF and i am trying to create a WPF form and trying to call from another application . I am converting the WPF output as class libarary and calling from another Solution .
There is a .cs file which call this wpf window from code behind using below code .
Thread thre = new thread(()=>
{
mainwindow md = new mainwindow();
md.ShowDialog();
md.Closed+=(s,e)=> md.dispatcher.InvokeShutdown();
Dispatcher.Run()
});
thre.SetApartmentState(ApartmentState.STA);
thre.Start();
I Can able to call my window and all my functionality working excel the dispachter.beginInvoke is not triggering .And i also get Application.Current =null . I am unable to go to if statement in the below code.
Method in window.cs
new Thread(()=>
{
rsult= getItemID("44");
Dispatcher.BeginInvoke( new ThreadStart(()=>{
if(rsult==0)
{}
});
}).Start();
}
ShowDialog() blocks. You should register your event handler, show the window by calling the Show() method and then start the message pump by calling Run():
Thread thre = new thread(()=>
{
mainwindow md = new mainwindow();
md.Closed += (s,e) => md.dispatcher.InvokeShutdown();
md.Show();
Dispatcher.Run()
});
thre.SetApartmentState(ApartmentState.STA);
thre.Start();

Prism MVVM - Showing Pop up window from viewmodel on a button click command in WPF

I have a datagrid in my view(UserControl) in which I have a button, The requirement is to show a window on click of that button. I achieved it by creating an object for the window and calling it's show method and yes it's a wrong way, So, I want a standard way of achieving it.
I'm using Prism framework, So I mapped the window view with Window viewmodel using ViewModelLocationProvider in the windowviewmodel.
var table = new Window();
table.Content = new windowViewModel();
table.Show();
This is the code I implemented in the main viewmodel on click of the button.
It is actually opening a window, but, view is not getting loaded on the window.
Use the IDialogService Introduced in Prism 7
first the dialog view or ViewModel needs to implement the IDialogAware interface like this:
class PopupViewModel : BindableBase, IDialogAware
{
public string Title => "Popup";
public event Action<IDialogResult> RequestClose;
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public DelegateCommand OkCommand => new DelegateCommand(() =>
{
//you can also pass any parameters you want to back pass to the caller
RequestClose.Invoke(new DialogResult(ButtonResult.OK));
});
public void OnDialogOpened(IDialogParameters parameters)
{
//here you get the parameters you passed;
}
}
then you need to register your view like this
containerRegistry.RegisterDialog<Views.Popup>();
to use you inject into your ViewModel the IDialogService and call it
this.dialogService.ShowDialog(nameof(Views.Popup), dialogParmaters, (result)=>
{
if(result.Result == ButtonResult.OK)
{
}
});
you can also register your custom window if you want the window needs to implement IDialogWindow
containerRegistry.RegisterDialogWindow<MyDialogWindow>();
First, you want the view model to be the DataContext (the Content is in fact the view). I'd advise againt the ViewModelLocator here, because it makes it impossible to pass parameters to the new window. Probably, you want to show different content depending on which row you click the button in.
new Window { DataContext = new WindowViewModel( myRow ) }.Show();
Second, there's nothing wrong with this approach but for one minor remark: put the code that shows the window in a service. You want to unittest your view models and that doesn't go well with opening real windows.
public interface IWindowService
{
void ShowWindow( SomeParameter parameter );
}
If you inject that into your view model, you can still test it (verify that ShowWindow is called).
Third, remove calls to new and replace them with calls to injected factories.
var viewModel = _viewModelFactory.Create( "some parameter" );
is a lot nicer than
var viewModel = new ViewModel( "some parameter", new ADependency( new OtherDependency(), new SomeService() );
not to speak of the difficulties if singletons are involved.

WPF window owner property issue

I have a WPF MainWindow where I can open a second one as follow, taking as an example this post:
var win = new CalibrationWindow(){Owner = this};
win.ShowDialog();
Rarely happens that I have the following runtime exception "cannot set owner property to a window that has not been shown previously".
Do you have any suggestions? Thanks in advance.
Handle the StateChanged or Activated event of the window and set the Owner property in this event handler as suggested here:
Having Trouble Setting Window's Owner in Parent's Constructor
var win = CalibrationWindow();
this.Activated += (s, e) => { win.Owner = this; };
win.ShowDialog();

Routed event class handler for LoadedEvent does not work for most classes

I'm trying to register handler for all Loaded events:
EventManager.RegisterClassHandler(typeof(UIElement), FrameworkElement.LoadedEvent, new RoutedEventHandler(OnRoutedEvent), true);
EventManager.RegisterClassHandler(typeof(ContentElement), FrameworkContentElement.LoadedEvent, new RoutedEventHandler(OnRoutedEvent), true);
EventManager.RegisterClassHandler(typeof(UIElement), FrameworkElement.UnloadedEvent, new RoutedEventHandler(OnRoutedEvent), true);
EventManager.RegisterClassHandler(typeof(ContentElement), FrameworkContentElement.UnloadedEvent, new RoutedEventHandler(OnRoutedEvent), true);
Unfortunately my handler is only called for Window and descendants of DatePicker. It does not work for any other type.
Can anyone explain this behavior ? It's a bug, sadly they've chosen to ignore it.
Is there some other way to be notified about any new element in application/window ?
Perhaps you could define an AttachedProperty/Behavior<T> that uses FrameworkPropertyMetadataOptions.Inherits, and then specify it on your root element, and in the behaviour hook the Loaded/Unloaded events on each instance

WPF image visibility is not changing

I have the following method in my WPF project (.net 4):
private void MyMethod(){
imgMyImage.Visibility = Visibility.Visible;
DoWork();
imgMyImage.Visibility = Visibility.Collapsed;
}
The image is in a DockPanel, and I want it to appear while the "DoWork()" method is being executed, but it does not change state until after the "MyMethod()" method exits. Can someone explain how to make this work correctly?
Thank you for any help.
Your "DoWork" method is blocking the UI thread. Until it completes, nothing in the UI will change (and the UI will remain unresponsive).
A better option is to push the DoWork into a background thread. For example, using the new Task framework in .NET 4, you could write this as:
private void MyMethod()
{
imgMyImage.Visibility = Visibility.Visible;
// Create a background task for your work
var task = Task.Factory.StartNew( () => DoWork() );
// When it completes, have it hide (on the UI thread), imgMyImage element
task.ContinueWith( t => imgMyImage.Visibility = Visibility.Collapsed,
TaskScheduler.FromCurrentSynchronizationContext() );
}

Resources