I'm using HwndSource in a WPF window, which is not the main window, in order to hook a window procedure (WndProc) to receive some messages:
WinSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
WinSource.AddHook(new HwndSourceHook(WndProc));
HwndSource implements IDisposable. MSDN is not clear about when/should I dispose it. The docs of HwndSource.FromHwnd explains the technique above:
You can use this method to return an HwndSource for a window that is not explicitly an interoperation window. The procedure for this is:
Create a WindowInteropHelper instance (providing the main Window as a constructor parameter).
Get the value of the Handle property from that WindowInteropHelper instance.
Pass that HWND value as a parameter to FromHwnd.
And then:
This technique can be useful if you then want to add general AddHook message processing to the window. However, whenever you create an HwndSource, you are also responsible for destroying it. This is true even if the Application object for an application HwndSource is disposed.
(the emphasis is mine)
However, at the HwndSource class doc, we see:
Object Lifetime
An HwndSource is a regular common language runtime (CLR) object, and its lifetime is managed by the garbage collector. Because the HwndSource represents an unmanaged resource, HwndSource implements IDisposable. [...] Calling Dispose explicitly from the interoperating code might be necessary for certain interoperation scenarios.
And regarding the hook:
The actual hooks are held by a weak reference. Therefore, make sure that you manage the lifetime of your hook delegate.
I can't give a full answer to this, but based on recent experience I can say that you should not dispose the HwndSource object too soon - specifically, not at all until the window it refers to is closed.
I was just debugging a scenario that was done like this:
using(var source = HwndSource.FromHwnd(window.HWnd()))
{
source.AddHook(hook);
}
The result of this was that the window became nonfunctional (no longer processing messages) right after the source was disposed.
Looking briefly into the reference source for FromHwnd(), it seems that it will always return you the same object for the same window. I think this is why you cannot dispose source just because your own code is done with it. Apparently HwndSource.Dispose() doesn't just clean up the HWndSource object, but some of the unmanaged window itself.
Having noticed this, now I also see the HWndSource documentation says:
Synchronously calling Dispose immediately destroys the Win32 window
which seems to be what I've observed.
Related
I am using WPF. I have a static class that performs some setup not available during design mode. This constructor gets called by a window in design mode, which results in an exception being thrown.
How do I detect design mode in a static method, so I can invoke the appropriate design mode behavior?
The recommended approach does not work for static methods.
Edit:
The static constructor is called from xaml, so I can't conditionally call it (unless I move the call to code-behind, which I'd like to avoid).
In the window: <Window ... HelpProvider.Keyword="some_help_topic.html">
In the class:
static HelpProvider()
{
// Load the .chm file from an application setting (this fails at design time)
// Add a WPF command binding
}
The possible way to solve it keeping attached property in xaml file is:
Move initialization code from static constructor to attached property changed callback. Frankly speaking, it is not good practice to do such kind of work in static constructors.
In your attached property changed callback you have a reference to your window. So you can call DesignerProperties.GetIsInDesignMode(yourwindow) there and decide, if you need to load file or whatever causes issues.
i am trying to call a function in Form1 from WPF window and i am getting the following error
"Reference to a non-shared member requires an object reference."
also getting the same error when trying to access the Public variables in Form1 from wpf window.
is it not possiable to do it?
So according to the MSDN this error, this is a problem with trying to reference instance variables as if they are static.
If your class is Form1, you cannot access methods or variables that are not static by calling Form1.Method(). This won't work ever, not just in WPF. This is pretty basic stuff, you might want to read up more on VB. Check out Shared and Static documentation.
To access, for example, the method Show() on Form1, you must instantiate (create an instance of an object), and call the method on your object. Like this.
Dim frm As New Form1()
frm.Show()
I'm not even sure if this is even possible, but I've just started WPF development on a few new projects and tried to wrap up some common functionality by creating a mini-framework. Just things like exception handling and thread management.
What I would like to do is replace this line...
public partial class App : Application
with
public partial class App : MyFrameworkApplication
I've got the libraries set up and referenced, but I get an error regarding the 'partially' declared App class, presumably because it's still referencing the old base class.
Any ideas? Thanks.
EDIT: #Jeff M: No, your solution didn't work. I suspect because the MyFrameworkApplication is actually in a library and the z namespace declaration fails to recognise the library's namespace. I've got it referenced in the App.xaml.cs, but the suspicious looking error is:
Error 3 Undefined CLR namespace. The 'clr-namespace' URI refers to a namespace 'MyLibraryNamespace' that is not included in the assembly.
I can circumvent the problem by creating a proxy class within the local namespace and having it derive from the library class...but it's a bit smelly.
I suspect it's because the the underlying XAML root is still an Application as opposed to MyFrameworkApplication. I'd guess the generated baml uses the root as it's parent class. Try changing it to the appropriate names.
e.g.,
<z:MyFrameworkApplication x:Class="MyNamespace.App"
...
xmlns:z="clr-namespace:MyNamespace">
...
</z:MyFrameworkApplication>
It seems my suspicions were correct.
From the docs in Code-Behind and XAML in WPF:
Code-behind, Event Handler, and Partial Class Requirements in WPF
The partial class must derive from the type that backs the root element. (emphasis mine)
Note that under the default behavior of the markup compile build actions, you can leave the derivation blank in the partial class
definition on the code-behind side. The compiled result will assume
the page root's backing type to be the basis for the partial class,
even if it not specified. However, relying on this behavior is not a
best practice.
The event handlers you write in the code behind must be instance methods and cannot be static methods. These methods must be defined by
the partial class within the CLR namespace identified by x:Class. You
cannot qualify the name of an event handler to instruct a XAML
processor to look for an event handler for event wiring in a different
class scope.
The handler must match the delegate for the appropriate event in the backing type system.
For the Microsoft Visual Basic language specifically, you can use the language-specific Handles keyword to associate handlers with
instances and events in the handler declaration, instead of attaching
handlers with attributes in XAML. However, this technique does have
some limitations because the Handles keyword cannot support all of the
specific features of the WPF event system, such as certain routed
event scenarios or attached events. For details, see Visual Basic and WPF Event Handling.
The root application type in code-behind and in the xaml must agree.
I have a windows form that contains many controls e.g timers, gridviews, and binding sources etc, and all of these expose a dispose function. Do I have to call their dispose function in this
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
// do I have to write something here ???
base.Dispose(disposing);
}
also what does components.Dispose() exactly do?
thanks
Generally when you add controls onto your forms via the toolbox in Visual Studio, the controls will automatically be Disposed for you (in the protected override void Dispose method).
The only time you do need to manually dispose objects is when you manually create other disposable objects that implement the IDisposable interface, things like file handles (Stream, StreamReader...), GDI objects (Bitmap, Brush) and unmanaged resources. Manually releasing objects of this type ensure you follow good coding practice by releasing the resources you create.
No, the form will call Dispose for you.
What is Dispose for? This is taken from here IDispose
Use the Dispose method of this
interface to explicitly release
unmanaged resources in conjunction
with the garbage collector. The
consumer of an object can call this
method when the object is no longer
needed
The base.Dispose call invokes the System.Windows.Forms.Form.Dispose, which disposes menus and other form controls. The call ends up in System.Windows.Forms.Control.Dispose, which recursively disposes all child controls.
I guess you don't need to worry as long as your control is reachable from the form, either directly or transitively.
One-line summary: What is the best practice for unhooking event handlers created in the constructor of a UserControl in Silverlight2?
Background:
I am currently building a line-of-business application in Silverlight2. As Silverlight is a browser plugin, there is no concept of a Window - everything is done within UserControls. The way I'm handling different "forms" in the application is to have a top-level usercontrol that contains a Viewbox. To show different forms, I set the Child property of the Viewbox to different UserControls. My app has a singleton PageManager class that is called to open and close forms. The forms (UserControls) are stored in a stack. Opening a form puts it on the top of the stack, closing it removes it from the stack and shows the one below it.
I'm trying to follow the Model-View-ViewModel pattern. In each form (derived from UserControl), I have a ViewModel that manages all the data for the View. The ViewModel exposes events so the UI can be notified when operations such as load and save have completed.
In my form, I subscribe to the event in the constructor, after I've got the ViewModel
public partial class MyPage : UserControl
{
public MyViewModel ViewModel{get; set;}
// other constructors, which create the viewmodel and call the constructor below.
public MyPage(MyViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
this.LayoutRoot.DataContext = this.ViewModel;
// subscribe to event so we can do stuff
this.ViewModel.LoadCompleted += new MyViewModel.LoadCompletedEventHandler(ViewModel_LoadCompleted);
}
My question is: Now that I've subscribed to this event, when do I remove the handler? Do I create a destructor and do it there, or does that create a chicken-and-egg situation where the garbage collector wont destroy the object until all references (ie: the event handlers) are gone? Do I create an interface that the forms must implement that specifies an UnhookEvents function that's called when the form is closed by the PageManager?
Edit: Thanks for the responses. What about the situation where the ViewModel lasts longer than the form (UserControl)? Part of my app allows users to create what is quite a complex structure, but in 95% of cases it's much simpler. What I've did was create 2 forms that use the same ViewModel. Users can start filling out the simple form, then switch to advanced mode, which creates a new form, passing the ViewModel to it.
In the simple setup form:
private void AdvancedSessionSetupButton_Click(object sender, RoutedEventArgs e)
{
PageManager.GetPageManager().Close(this);
PageManager.GetPageManager().Open(new CreateSessionPage(this.ViewModel), "Create Session");
}
In the advanced setup form:
private void BasicSessionSetupButton_Click(object sender, RoutedEventArgs e)
{
PageManager.GetPageManager().Close(this);
PageManager.GetPageManager().Open(new CreateBasicSessionPage(this.ViewModel), "Create Session");
}
After PageManager.Close, the only things referencing the form are the events within the ViewModel. I guess that's where I should be unhooking them.
A destructor, more commonly known to C# programmers as Finalizers, is not necessary in this case. Assuming that ViewModel_LoadCompleted is a member function, it contains a pointer to "this" which you are giving to the ViewModel object which is fully contained by "this". The garbage collector should intelligently ignore this.
In this case, the correct thing to do is to not waste time unbinding them.
In general, you need to unbind an event handler when you pass "this" (explicitly, or implicitly) to some object which will hold that reference longer than the intended lifetime of "this". For example, if you set a handler on a parent control's event. Now the parent has a reference to you via the handler as well as in its Children controls collection. In this case, you should unbind when you are removed from the parent.
When in doubt, implement IDisposable and unbind in the call to Dispose().
Events are automatically unbinded when the garbage collector goes through your object.
But you can explicitly unbind them with the "-=" syntax at anytime:
this.ViewModel.LoadCompleted -= ViewMode_LoadCompleted;
You can implement a destructor:
~MyPage
{
this.ViewModel.LoadCompleted -= ViewMode_LoadCompleted;
}