As the title describes, I want to convert System.Windows.Controls.Textbox to IWin32Window.
I read How to use a FolderBrowserDialog from a WPF application
but it only describes how to get handle of winform, not control on it.
Thanks
WPF does not use Win32 handles for individual controls like TextBox, only for the Window itself. In other words, from Win32's perspective the entire WPF Window object is a single window with single handle.
Because of this, it is meaningless for an IWin32Window to return the "actual" Win32 handle of a WPF TextBox: A WPF TextBox simply doesn't have a Win32 handles. Thus you will have to return a Win32 handle of some other object.
How to do this depends on what you will be using the IWin32Window for. There are several possibilities for creating a Win32 window to correspond to your TextBox:
You could create a transparent Win32 window that overlaps the TextBox (useful for hit-testing or overdrawing scenarios)
You could create a zero-size window that is centered on the TextBox (useful for dialog initial-location and ownership scenarios)
You could host the TextBox in an ElementHost rather than in a WPF Window (useful if you want the TextBox to fit in with other Win32 stuff, such as an old MFC application)
You could host the TextBox in an ElementHost inside a WindowsFormsHost (useful if you need a Win32 window around the TextBox but still need WPF layout
Notes on the "extra window" solutions (1 & 2)
To create a Win32 window that overlays the TextBox (either transparent or zero-size), you would use traditional Win32 or WinForms techniques.
Since the TextBox can move on the screen you would need to move the Win32 window whenever the TextBox moves. This can be done in the OnRendering event using textBox.TransformToAncestor(window) then transforming to device coordinates using PresentationSource.TransformToDevice.
Notes on ElementHost solutions (3 & 4)
This is as simple as wrapping the ElementHost around the TextBox in your XAML, so this:
<Grid>
...
<TextBox ...>
</Grid>
might become:
<Grid>
...
<WindowsFormsHost>
<ElementHost>
<TextBox ...>
</ElementHost>
</WindowsFormsHost>
</Grid>
This can also be done in code by removing the TextBox from its parent, adding it to a newly-created ElementHost, and then adding the ElementHost to a newly-created WindowsFormsHost and adding the WindowsFormsHost back to the parent.
Note that WPF styles and properties (including DataContext, TextElement properties, etc) do not propagate down through ElementHost, even if wrapped inside a WindowsFormsHost, so the desired settings and resources must be propagated manually.
Related
We are creating some WPF UserControl which will utilize some WinForms or ActiveX control by using a WindowsFormsHost. For example, in one UC we have such code:
<WindowsFormsHost Name="windowsFormsHost1" Height="Auto" MinHeight="400" MinWidth="400">
<viewer:ReportViewer x:Name="viewerInstance" />
</WindowsFormsHost>
where the ReportViewer can be found in Microsoft.Reporting.WinForms.
In another UC the code is like this:
<WindowsFormsHost Name="windowsFormsHost1" Height="Auto" MinHeight="400" MinWidth="400">
<AxOWC:AxPivotTable x:Name="pivotTable" />
</WindowsFormsHost>
where the AxPivotTable can be found in AxMicrosoft.Office.Interop.Owc11
Both ReportViewer and AxPivotTable controls have their own context menu which include many use functionality. I'd like to keep them. But I also need to add some new functions. In another word, I want to design an enhanced context menu, with the default context menu being part of it, and my customized menu items being other parts .
And here comes the problem: I really don't know where to add my customized context menu items. I tried to add a context menu object to WindowsFormsHost. But the result is this customized menu will not be showed at all. I further set the WindowsFormsHost.ContextMenu.IsOpen to true, and this time the result is my customized menu will shadow the default context menu of the controls.
I also try to add the menu items from code-behind. For example, the ReportViewer derives from WindowsForms (not WPF assembly), which has a member called ContextMenu. But when I check viewInstance.ContextMenu.MenuItems, I see it actually has ZERO count collection, which means the default context menu doesn't exist on this level. So how can I find the default context menu and add my customized menu items then?
You can't overlap WPF content with non WPF content (unless you are using D3DImage)
I have a few usercontrols loaded into a tabcontrol via MVVM in WPF.
Within the XAML for the usercontrol I am setting focus to a textbox using the FocusManager, however this appears to only work when the first instance of the usercontrol is created.
Just to test I added a loaded event handler to the usercontrol - this is only called on the first instance.
I'm using data templates for the user controls as follows:
<DataTemplate DataType="{x:Type local:UserTypeViewModel}">
<local:UserTypeView />
</DataTemplate>
The textbox is focused as follows:
FocusManager.FocusedElement="{Binding ElementName=txtName}"
Additionally I'm using a global event handler (for the textbox GotFocus event) which selects all the text using a dispatcher.
If anyone has any tips on how to achieve focus with every usercontrol I'd be very grateful.
Thanks, Ben.
Remember that a visual element can only receive focus, if:
It is visible (in a TabControl only one tabitem can be visible at a time
IsFocusable must be set to true (is default false for UserControls)
It has finished loading (as you write - do it in the Loaded event))
I think the first reason is why it only works for the first element.
As for how to achieve it for all controls - you can use a style with an EventSetter for the Loaded event. You need to make a style per type of control though to avoid having to set it for each control.
Anyone got any neat solutions to prevent a Silverlight ChildWindow being moved?
thanks,
Mark
I'm not sure you'd call this neat but...
Create yourself a new Templated control and call it ImmovableChildWindow.
Modify the class it inherits from to be ChildWindow.
Open Themes/generic.xaml you will find an initial style for the ImmoveableChildWindow
In the Silverlight documentation you'll find the existing template for a ChildWindow at ChildWindow Styles and Templates.
Note the existing TargetType value for the ImmovableChildWindow style.
Copy'n' paste the whole default style for a ChildWindow from the documentation into your themes/generic.xaml file.
Replace TargetType for this copy to the same value as the exiting ImmovaleChildWindow style.
You can now delete the initial style. Leave only the large copy of ChildWindow style now targeting ImmovableChildWindow.
Find within the Template setter change the TargetType of to the same value as the style TargetType
Search through the template and find a Border with the name Chrome. Delete the x:Name="Chrome" attribute. (This is what we are really after).
Now when you create a new ChildWindow item it will by default inherit form ChildWindow, if you want it to be immovable you need modify it to inherit from ImmovableChildWindow instead (change the base type in the code-behind and the root tag name in the xaml).
The ChildWindow attaches events to the FrameWorkElement with the name "Chrome" which enables the child window to be moved about. However being a well-behaved templated control, if it can't find a FrameworkElement called "Chrome" it just continues to work without that feature.
Not Required to Create new class, instead
Copy the style from: http://msdn.microsoft.com/en-us/library/dd833070%28VS.95%29.aspx
Give x:key="stylename"
In Construtor of Childwindow, paste following code before InitializeComponent:
this.Style = App.Current.Resources["childWindow"] as Style;
above solution resolved my issue
Maybe you can try this simple way to do that:
Create a Grid to warp all the content in your ChildWindow.
<Grid Margin="0">
<!--Your ChildWindow. Canvas, Grid, Textblock...Whatever-->
</Grid>
Since the Grid has a 0 margin, you can not click it and move it.
I've created a simple UserControl in ExpressionBlend. The UserControl is a ractangle with a TextBlock in it. When i use this UserContol in a Silverlight project, i can not change the text in the textBlock of the control. Should give an acces to the TextBlock before using the Control?
HELP"_
Your user control should have public properties that map to its features. If you want the users of the control to be able to set the text, create a Text property. The implementation can be as simple as forwarding to the inner TextBox.
Exposing the inner control is not the right way to do it.
I am attempting to add a WPF usercontrol to an existing WinForms project and get the WPF UserControl to dock and fill the entire space.
There's a current framework that loads WinForms UserControls into a parent form (into a panel) in response to button clicks. This is where I'm trying to hook in - The WinForms UserControl that's currently getting loaded will have the ElementHost.
Hierarchy:
Form1.cs - contains a panel that gets WinForms UserControls dynamically loaded
WinForms UserControl - contains the ElementHost
WPF UserControl
The ElementHost has Dock set to Fill and its Child property set to ucReport, which is a WPF UserControl, which has the following markup (only top level design included):
<UserControl x:Class="MyClassName"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TabControl HorizontalAlignment="Left" Name="tabControl1">
<TabItem Header="Header1">
...The interesting stuff goes here
</TabItem>
</TabControl>
</UserControl>
The content of the UserControl does expand vertically when I resize the form, but horizontally, the content only expands large enough to accomodate its content.
When I view the WinForms UserControl (the one that has the ElementHost) in the designer, the problem is apparent. The WPF content that's specified is getting rendered and it's filled top to bottom, but not left to right.
I'm of the mind that it's something in the XAML that has to be set (perhaps on the UserControl declaration?) to get it to fill it's parent container, which is the ElementHost - I just can't find the property.
Would someone enlighten me?
Change HorizontalAlignment to Stretch or get rid of it entirely.