I am trying to host a custom Windows Forms control in WPF. My custom control does not have a public constructor, and it has a static Create() method which looks something like this:
public abstract class MyCustomControl : UserControl
{
internal MyCustomControl(...) { }
public static MyCustomControl Create(SomeEnum kind)
{
switch (kind)
{
case SomeEnum.Kind1:
return new MySuperCustomControl(...);
...
}
What I want to do is instantiate this custom control in WPF and then have it hosted in WindowsFormsHost, but I obviously can't add an abstract class:
<wfi:WindowsFormsHost Width="250" Height="150">
<my:MyCustomControl x:Name="customControl" /> <-- doesn't work
</wfi:WindowsFormsHost>
Is there a way I could add it into the "Host" via code?
You can't host control without public constructor in XAML.
You can try two way:
define name for your
WindowsFormsHost and set Child
property of WindowsFormsHost to your
instance from static Create() in C#
code. for example in initialize (or
load) method. - it is simple way.
try to bind Child property of WindowsFormsHost to Create() method.
Frankly, I don't know or this
approach will be work... but you can
try :).. how bind to method in XAML?
you can read - this or try to
look in msdn or google :)
Found it, it's the WindowsFormsHost.Child property.
Related
I am trying to refill GridView on a Usercontrol (DashboardCTR) by calling a method (Reload_Dash) in the Usercontrol from a different form (FrmOpenShop) without creating a new instance of the UserControl.
I achieved this same task when using form like this:
foreach(Form appForm in Application.OpenForms)
{
if(appForm.Name=="formName")
{
(Application.OpenForms["formName"] as formName).MethodName;
}
}
But for Usercontrol, am not user of how to get this done, i was hoping I could get it by following the approach stated above like this:
foreach(UserControl control in Application.OpenForms)
{
if(control.Name=="DashboardCTR")
{
(Application.OpenForms["DashboardCTR"] as DashboardCTR).Reload_Dash;
}
}
But this didn't work, some idea would be helpful.
Thanks.
A component's/control's Modifiers property annoyingly defaults to private when created, or if not that case, try adding in these protection modifiers: public and static, public goes before static.
The public modifier makes the method available to the user if the constructor is used.
The static modifier forces the method available only if the type is mentioned without using a constructor. This allows you to force a reload/redraw on the UserControl grid view or whatever. Allowing you to refresh it anytime you want.
I have an issue, and I don't know if I can do that, or if there is another way to do that. I have an abstract class called "BasePage", it is my .NET Standard library, so I can't access to System.Windows namespace. Its declaration is:
public abstract class BasePage<VR> where VR : new()
EDIT: The class above has a public property to access to VR
So now, for each platform (WPF, Xamarin, etc) I have to create its own implementation of the class begin VR the content control of each platform (UserControl for WPF, for example). I already did it and this is:
public class WindowsBasePage : BasePage<UserControl>
Now, every time I want to create a page to add content to a window, I have to create something like this:
public partial class UserPassPage : WindowsBasePage
{
public UserPassPage()
{
InitializeComponent();
}
}
The problem becomes when I have to set it in the XAML file (the View). I can create it and it builds:
<local:WindowsBasePage x:Class="Bitture.AppManager.Manager.UserPassPage"
[...]
xmlns:local="clr-namespace:Bitture.AppManager.Manager"
mc:Ignorable="d" >
</local:WindowsBasePage>
but I can't add components (like buttons, text, grids, stackpanels, etc). I want to know If I can do it with my current code or there is something I have to change. Because I have to access to the generic type WindowsBasePage that inherits from
class WindowsBasePage : BasePage<UserControl>
I am not sure what you are trying to do here but you can't add UIElements to a custom class of yours that doesn't inherit from any of the common WPF base classes such as for example Panel or ContentControl, and expect it to be rendered as a UserControl or some other WPF control.
This won't work. WPF knows about how to render WPF controls but it doesn't know how to render a custom BasePage<UserControl>.
I need to create a custom User Control with generics because I have a BindingSource with a data source of type T
public partial class ABMControl<T> : UserControl
{
public ABMControl()
{
InitializeComponent();
this.bindingSource.Datasource = typeof(T);
}
}
In the form designer the custom user control does not appear in toolbox because is generic.
What is the solution?
It's expected behavior for toolbox.
When dropping a control from toolbox onto your form, you are commanding the designer to create an instance of that control. You cannot create an instance of GenericControl<T> without determining T. Instead you need an instance of GenericControl<SomeClass>.
So it completely makes sense the generic control doesn't appear in toolbox because it has no usage in designer and designer doesn't know what type should it use for generic parameter when creating instance.
Also about designer, considering this post: Generic Base Class for UserControl starting from VS2015.1, Windows Forms Designer shows classes which have generic base classes without any problem. The following class will be shown in designer without any problem:
public class SomeClassControl:GenericControl<SomeClass>
{
}
For older versions of Visual Studio, use the workaround which is described in the linked post:
public class SomeClassControl:SomeClassControlBase
{
}
public class SomeClassControlBase:GenericControl<SomeClass>{}
I'm writing a wpf program that needs several usercontrols that look exactly the same but perform different functions. With winForms, I could just extend the base control and add the functionality, but as far as I know, it's impossible to inherit xaml files. Is there any way I can have different codebehind classes that all use the same xaml file for their control?
You might be able to do this using MVVM pattern and create multiple VMs which perhaps implement the same interface. The XAML view could then be bound to any of your VMs relying on the fact they share the same interface.
In this approach you'd not use the code behind at all.
One way to do it is by using inheritance. A very simple example would be a UserControl with a single button, that should display different contents in a MessageBox.
We will have something like this:
public abstract class SomeUserControl : UserControl
{
//declared by XAML (can be made public with x:FieldModifier="public")
public Button MyButton;
//code-behind
public SomeUserControl() {
InitializeComponent();
}
}
public class MySpecialControl : SomeUserControl {
public MySpecialControl() {
MyButton.Click += (sender, e) => MessageBox.Show("Bla");
}
}
To use the MySpecialControl, just declare it in XAML like you did with your previous one:
<myNamespace:MySpecialControl />
Note that you can also create an abstract method for the button click, if the variation in behavior is not so big.
With winForms, I could just extend the base control
And one can't do similar in WPF?
Create a custom composite control with a dependency property(ies) which would set the mode of the control to fit its the target consumer's needs.
The control could be based on an existing control or controls.
I'm making such a tabbed "Product Version Control", using an UserControl which encloses fields, checkboxes, text areas, grids, and so on. At runtime, when I add a new tab (like we have on browsers), I instantiate a new UserControl (with all components inside). The issue is: I can get all internal component values and fill an object to persist, but not the other way. I can take all values from Object and set them to EditValue (or Text/Value properties) properties of internal components, but they are not showing up to the user.
Consider:
All my internal components have public set/get methods like shown below
public class TabVersion : UserControl
{
...
public DevExpress.XtraEditors.SpinEdit seRevision
{
get
{
return _seRevision;
}
set
{
_seRevision = value;
}
}
...
}
Inside TabVersion class, I have a "fill" method which receives an "Version" object and set all internal components "EditValue" properties like shown below:
public class TabVersion : UserControl
{
...
public void FillTab(Sheet sheet)
{
...
this.seRevision.EditValue = sheet.NumRevision;
...
}
...
}
At runtime, all EditValue component properties are filled but not showing to the user. Do I have to set "Enabled" or "Visible" properties for each component inside my usercontrol?
Any Ideas?
Thank you in advance.
Well... After googling everywhere with no goal, I wrote a "Fill" method that fills all DevExpress controls inside my user control, and called it inside the "Shown" event at the parent form. I think that's a bug from DevExpress, because all Windows default components works all right when I give them their respective values. That's it.