WPF - Catel - Disable CommandManager for Window in different Thread - wpf

Because the PleaseWaitService was removed with Catel 5.0.0, I copied the sourcecode of the implementation out of version 4.5.0 in an separate lib and linked the "new" lib and used the Service like before.
But because there were some errors with the PleaseWaitService in combination with our existing codebase I rewrote and simpliefied the Service (just supporting WPF).
Now I'm showing the PleaseWaitWindow in a different Thread which works in my testproject but not in production. I'm getting an InvalidOperationException when I call window.Show() (the window was created in the same thread).
In the exception's stacktrace are some calls from the Catel CommandManager
at System.Windows.Threading.Dispatcher.VerifyAccess()
at Catel.MVVM.CommandManager.SubscribeToKeyboardEvents(FrameworkElement view) in C:\CI_WS\Ws\107901\Source\Catel\src\Catel.MVVM\Catel.MVVM.Shared\MVVM\Commands\CommandManager.wpf.cs:line 64
at Catel.MVVM.CommandManager.OnWindowLoaded(Object sender, RoutedEventArgs e) in C:\CI_WS\Ws\107901\Source\Catel\src\Catel.MVVM\Catel.MVVM.Shared\MVVM\Commands\CommandManager.wpf.cs:line 78
[...]
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
I have registered one Command in the CommandManager which won't be used in my custom PleaseWaitWindow.
So my question is: How can I disable the standard injection from the Commandmanager into the window?
Regards

The advantage of Catel is that everything is pluggable. If you want different behavior for the command manager, you can create your own version and override the things you want differently. Don't forget to register it in the ServiceLocator.

Related

Minimize window using Windows 11 animation effect

There are two (it would seem) idiomatic ways to minimize a WPF window in code:
window.WindowState = window.WindowState.Minimized
SystemCommands.MinimizeWindow(window)
The desired behavior is that the windows 11 window minimize animation is seen. The actual behavior is that the window instantly disappears from the screen.
Please note: This is for a window with a custom chrome - therefore triggering the behavior from code seems necessary:
<Window
WindowStyle="None"
AllowTransparency="True
Background="Transparent">
<!-- custom windows chrome here -->
</Window>
Is this a defect in the WPF desktop pack for .NET 5 (and 6)?
How does one not get the desired behavior without reverting back to default windows with standard chrome? It is not an option to use a WinUI 3.0 window since XAML islands have not been released yet and gradual modernization is needed.
There are some proposed solutions on the web, like:
https://coderedirect.com/questions/352460/custom-window-style-with-minimize-animation
And the other (old) stackoverflow question:
Custom window style with minimize animation
However, I could not get it to work with a window with a transparent background.
===== update after issue was closed =====
Reviewer: please read this carefully before voting to close the issue again and point to exact workable solution.
Issues with existing answers:
First suggestion is to change WindowStyle, then WindowState; this poses a problem since it requires AllowTransparency=false which defeats the purpose of the exercise here - which is getting a custom chrome.
Other suggestion is to use Win32 API's. Again I tried to do that but it did not work in my setting. I haven't logged the exact error messages I got though. However, looking at the code again there is an obvious issue with it: it has the same window requirement as the first suggestion: the window must not be transparent - observe code from the old answer:
private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == ApiCodes.WM_SYSCOMMAND)
{
if (wParam.ToInt32() == ApiCodes.SC_MINIMIZE)
{
WindowStyle = WindowStyle.SingleBorderWindow;
WindowState = WindowState.Minimized;
handled = true;
}
else if (wParam.ToInt32() == ApiCodes.SC_RESTORE)
{
WindowState = WindowState.Normal;
WindowStyle = WindowStyle.None;
handled = true;
}
}
return IntPtr.Zero;
}
It seems to be on the roadmap in Themes of .NET for .NET 7:
Epic - Support Windows 11 look and feel for WPF controls
Also this amazing piece of open-source just landed:
WPF UI - Windows 11 styles and controls for WPF

NativeWindows or Win32?

I'm a bit confused about the difference between:
LRESULT CALLBACK WndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
and
virtual void WndProc(Message %m);
I know that the first is to get message to menage event in win32, but so "WndProc(Message %m)" is the same thing when we are programming a Windows Form project?
The last question is: When is better to use NativeWindow methods and when is better to use win32 methods to manage events?
My project is a simple window form with a panel, on the Panel I call a window where I can menage OpenGL operations.
Could someone help me?
The former is raw C-style Win32 API. The latter is a member of a .NET classes System.Windows.Forms.Control and System.Windows.Forms.NativeWindow, as expressed in C++/CLI.
I imagine that .NET runtime internally implements WndProc the Win32 callback, and arranges for it to call WndProc the class method, if you choose to override it in your class derived from Control.
I'm not sure why you need NativeWindow. If for some reason you want to handle raw window messages, then derive your class from Panel and override WndProc there; Panel derives from Control.

WPF XAML Designer Crashes

I have a Window, the only thing it has in it is a TextBlock. I'm getting ridiculous designer exceptions that is crashing the designer every time I change anything. I started removing everything trying to find the culprit of this error. And now I have nothing left, but the designer keeps throwing exceptions.
<Window x:Class="Company.Product.Views.About"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="397"
Width="658">
<TextBlock>Test</TextBlock>
</Window>
code behind:
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class About : Window
{
public About()
{
InitializeComponent();
}
}
If I "Click here to reload the designer" the window shows up, but then if I modify the text of TextBlock, I get an exception
Exception
System.ArgumentNullException
Value cannot be null.
at System.RuntimeType.MakeGenericType(Type[] instantiation)
at Microsoft.VisualStudio.Shell.Design.VsTargetFrameworkUtil.GetRuntimeType(Type type)
at Microsoft.VisualStudio.Shell.Design.VsTargetFrameworkType.TryGetRuntimeType()
at Microsoft.VisualStudio.Shell.Design.VsTargetFrameworkUtil.EnsureRuntimeType(Type type)
at Microsoft.VisualStudio.Shell.Design.VsTargetFrameworkProvider.GetRuntimeType(Type reflectionType)
at MS.Internal.Package.VSIsolationProviderService.RemoteReferenceProxy.VsReflectionResolver.GetRuntimeType(Type reflectionType)
at Microsoft.Windows.Design.Metadata.ReflectionMetadataContext.CachingReflectionResolver.GetRuntimeType(Type reflectionType)
at Microsoft.Windows.Design.Metadata.ReflectionMetadataContext.Microsoft.Windows.Design.Metadata.IReflectionResolver.GetRuntimeType(Type reflectionType)
at MS.Internal.Metadata.ClrType.get_RuntimeMember()
at MS.Internal.Metadata.ClrMember`1.Microsoft.Windows.Design.Metadata.Reflection.IReflectionMember.get_MemberInfo()
at MS.Internal.Metadata.ClrType.Equals(Object obj)
at System.Collections.Generic.ObjectEqualityComparer`1.Equals(T x, T y)
at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)
at Microsoft.Windows.Design.Metadata.Xaml.XamlExtensionImplementations.<>c__DisplayClass5.<FindAttachableProperties>b__4(ITypeMetadata walkType)
at MS.Internal.Design.Metadata.Xaml.XamlType.<GetAllAttachableProperties>d__7.MoveNext()
at MS.Internal.Design.Metadata.Xaml.XamlType.<FindAttachableProperties>d__0.MoveNext()
at Microsoft.Windows.Design.Metadata.Xaml.XamlExtensionImplementations.<FindAttachableProperties>d__7.MoveNext()
at MS.Internal.VirtualModel.VirtualModelPropertyCollection.<GetUncachedProperties>d__0.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at MS.Internal.VirtualModel.VirtualModelPropertyCollection.GetEnumerator()
at MS.Internal.Designer.PropertyEditing.Model.Properties.ModelPropertyMerger.<GetFirstProperties>d__0.MoveNext()
at MS.Internal.Designer.PropertyEditing.Views.PropertyEntryReader.RedraftEntries(IPropertyViewManager viewManager, Selection selection, Boolean attachedOnly, IEventCodeBehindProxy eventCodeBehindProxy, CategoryList categoryList)
at MS.Internal.Designer.PropertyEditing.PropertyInspector.UpdateCategories(Selection selection, Boolean attachedOnly, IEntryReader entryReader)
at MS.Internal.Designer.PropertyEditing.PropertyInspector.RefreshPropertyList(Boolean attachedOnly)
at MS.Internal.Designer.PropertyEditing.PropertyInspector.OnSelectionChangedIdle()
at MS.Internal.Designer.PropertyEditing.PropertyInspector.OnSelectionChangedIdleForced(Object sender, EventArgs e)
at System.Windows.Threading.DispatcherTimer.FireTick(Object unused)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
I'm left with no way to debug what the problem is, and frankly I getting frustrated considering there should be nothing on this simple example that should be crashing the designer. Any ideas?
Update
After re-installing and updating and reloading, problem went away temporarily. Now the problem is back again.
Actually, I'm not sure if the problem ever went away. I've also tried VS safe mode, /resetsettings, and deleting my several cache folders in the VS folder.
Update2
Here's a screencast which shows the problem Excuse my resolution, I'm in portrait.
Alright, I believe I fixed the problem. I created a new executable project, copied everything from the old one to the new one and tried deleting or adding items one by one to figure out what was special about that project.
It turns out that I'm referencing several 3rd party libraries by Actipro. Earlier, I had upgraded the libraries and copied them to a /lib folder and referenced them from there. One of the references was forgotten though, and I believe it was targetting an older version in the GAC instead of the /lib folder. I think I basically had two different versions of Actipro's shared library referenced.
After removing the erroneous reference to the old build for the 3rd party library, and updating it to the proper version as the others, the problem has gone away
The strange thing, is that the Window in question used no component or anything from that library. It may be that it was trying to resolve the Attached Properties inside the library (from the stack trace).
Try to set the TextBlock's content in the TextBlock.Text property:
<Window x:Class="Company.Product.Views.About"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="397"
Width="658">
<TextBlock Text="Test"/>
</Window>
Maybe that is the issues.

Custom properties on a win32 window

I've heard (well read, at http://www.ddj.com/windows/184416861), that it's possible to set custom properties on a Win32 window.
The trouble is, the download for the article above is on an ftp server that won't let me in.
As a bit of background info, I have a .NET app. The main window is registered to handle custom window messages. From a separate app, I need to post messages to this window. I can't find the window by caption as the caption changes. I can't find it JUST by window class, as the window class is the same for all forms in that app domain.
Ideally, I'd like to set a custom property on the Win32 window of the main form (Form1) that say, yes, this is form1. Then when I'm enumerating the windows of this app, I can tell that this is the required form by seeing if this custom property exists.
Cheers,
Steve
See here for an overview of window properties. Basically, you call the Win32 API function SetProp to set a window property and GetProp to retrieve it. There are a few more functions for enumerating properties and the like, but it sounds as if SetProp and GetProp is all you need.
As Martin says, the answer is the Win32 APIs GetProp and SetProp.
Here's what I now do when I create the main form:
[DllImport("user32.dll", SetLastError=true)]
static extern bool SetProp(IntPtr hWnd, string lpString, IntPtr hData);
SetProp( this.Handle, #"foo", new IntPtr( 1 ) ) ;
Now, I can check this property when enumerating the windows:
[DllImport("user32.dll")]
private static extern IntPtr GetProp(IntPtr hWnd, string lpString);
IntPtr result = GetProp( (IntPtr) hWnd, #"foo" ) ;

Silverlight Cache Control: Using revision number in url for XAP causes HyperLink to crash SL App!

To make sure all our customers receive the latest Silverlight App, we are placing the new revision number on the url for XAP file as follows:
<param name="source" value="/ClientBin/ShoeboxViewer.xap?v=5" />
Problem is when we do this, all HyperLink controls (in the Silverlight App) that use relative URLs, throw an internal error when clicked. Here's the stack trace:
Unhandled Error in Silverlight 2 Application Specified argument was out of the range of valid values. Parameter name: baseUri
at System.Uri..ctor(Uri baseUri, Uri relativeUri)
at System.Windows.Controls.HyperlinkButton.GetAbsoluteUri()
at System.Windows.Controls.HyperlinkButton.Navigate()
at System.Windows.Controls.HyperlinkButton.OnClick()
at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
at System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)
at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, String eventName)
If I remove the querystring, it works fine.
Can anyone help?
Cheers,
Ash.
Jacob is right - you might also want to look at this solution to fixup relative URLs.
The problem is actually that HyperlinkButtons can't use relative urls. I ran into this just the other day. It's a hack, but I got it to work by adding a click handler to the HyperlinkButton and then calling HtmlPage.Navigate, passing in a uri marked as relative

Resources