What I am looking for is the same type of designer support for controls inside a usercontrol. ie - resizing a textbox, moving a label, that are inside a usercontrol after placeing the usercontrol on to a form.
What I've been able to do...
create a usercontrol
use the designer to add controls to the it
create a new window forms app
add the usercontrol to the toolbox
drag and drop the control on the a form
where I am stuck...
edit the usercontrols controls. IE - being able to resize a textbox that is inside the usercontrol using the designer.
I found a similar question on stack that was never answered. So if I am being too vague you can follow this link https://stackoverflow.com/questions/10359772/example-make-constituent-controls-in-a-usercontrol-editable.
Thank you.
After reading Nikita's comment I was able to find Microsoft support page on creating a custom designer for controls.
Here's a quote if your interested on how the designed-time support works
The design-time support for components in the .NET Framework, however, is not defined exclusively by a design tool such as Microsoft Visual Studio .NET. Rather, the development environment supports the extension and definition of design-time behavior by classes such as designers that provide design-time support for components. Support for extensible and customizable design mode behavior is an integrated part of the .NET Framework. Tools such as Visual Studio .NET also provide a range of design-time services that designers can use.
This is the webpage if you like to continue reading and view samples from Microsoft
Enhancing Design-Time Support
Everything seems complicated when you just start learning it, heres a working code sample for a UserControl that has a PictureBox and a Label on it. Both controls can be edited during design time, ie. resizing and repositioning, and expose all their events and properties if you click on them.
You will need to add a reference to System.Design, which can only be referenced if you are not targeting ".Net Client Profile." You can change you target profile in Proprieties/Application/TargetFramework.
Add a usercontrol to your project and add a class to handle it's designer. Double click the usercontrol and then add a label and picture box from the toolbar.
Next open that class you create to be it's designer. Add this...
using System.Windows.Forms;
using System.Windows.Forms.Design;
public override void Initialize(IComponent component)
{
base.Initialize(component);
if (this.Control is MyUserControl) // replace this with your usercontrol type
{
// cast this.Control to you type of usercontrol to get at it's
// controls easier
var i = this.Control as MyUserControl; // replace ***
this.EnableDesignMode(i.label1, "unique_name1");
this.EnableDesignMode(i.pictureBox1, "unique_name2");
}
}
Related
Over a year ago I began writing a .NET Framework 4.6.1 app using Windows Forms. At the time I knew about WPF, yet was familiar with Windows Forms and it had most of the controls I needed. For the missing controls, I wrote two in Windows Forms and one in WPF. All of these coexisted fine, with the WPF control containerized within an element host.
This week I began the migration process to .NET Core 3.1. My tests with a copy of the project were positive, as well as initial results with the actual migration. After minor refactoring, the solution built and ran without issue. Then the gremlin appeared after opening the main UI form in the WinForms Designer. Back in .NET Framework, all of my custom controls appeared inside the Designer's Toolbox, providing easy drag-and-drop onto the form. In .NET Core, only my WinForms controls appeared in the Toolbox, not my WPF control. Because the Designer could not see that control, it stripped it from the Form's designer code, leaving an empty element host behind.
Here's the kicker. After reverting the Designer's changes, any direct manual edits to the Form's designer code is accepted, and building the project succeeds and runs fine. So for some reason the Designer does not like WPF controls in WinForms.
Things I've tried:
During my testing I discovered that the main WinForms UI needed both "UseWindowsForms" and "UseWPF" set to "true" for the project to compile. I then added the "UseWindowsForms" parameter to the WPF user control library. This caused the control to appear in the Designer's Toolbox, yet attempting to add the control resulted in this error: "Failed to create component ... Microsoft.DotNet.DesignTools.Client.DesignToolsServerException ... Make sure the type implements IComponent and provides an appropriate public constructor. Appropriate constructors either take no parameters or take a single IContainer parameter." And the existing WPF control in the code was still removed.
I copied the WPF control from the library to the main UI project, edited the namespace, and removed the library project reference. Same result as above.
Created a new Windows Forms User Control library, added "UseWPF" to the project, and copied the WPF control to this library. Same result as above.
Back to the test copy of my project, I followed Microsoft's guides for "try-convert" and "upgrade-assistant". The latter seemed promising at first, as it replaced, modified, or removed outdated referenced and packages. But, no success.
Tried the above migration steps with both .NET Core 3.1 and .NET 5. Same results.
The point I'm at now is to keep manually editing the Form's designer code. Not ideal for large changes, and also not sustainable if/when this project is passed to another developer. Any thoughts? Should I attempt porting the Windows Forms UI to WPF? Or is this simply a maturity issue with the still relatively new .NET Core Windows Forms Designer?
Visual Studio version: Community 2019 16.9.3
Screenshot of IComponent error:
enter image description here
I finally figured out a workaround; the idea was sparked by the Microsoft Docs page for the ElementHost control:
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.integration.elementhost?view=netcore-3.1
In essence, move the WPF control hosting from the main UI into a WinForms control library. Hence, the User control in this WinForms control library will be a wrapper for the WPF control. Here are the steps I took in my test VS solution:
Remove the "true" entry from the main UI project file I had added during testing.
In the new WinForms control library, add "true" to this project file underneath the "true" entry. This enables the library to be a bridge between the two UI frameworks.
If the WPF control to host is in a dedicated control library (like mine), then add this project as a dependency in the WinForms control library.
Create a new User control in the WinForms library, if there isn't one already.
In the Designer, add a panel container to the control with "Fill" docking. I named my panel as "panelWpf".
Here is where the Microsoft Doc comes in. In the code behind file for the WinForms control, I first added an ElementHost control and the WPF control as private global variables. Then, in the WinForms "Load" event, I set the ElementHost docking style, added the WPF as a child, and finally added ElementHost as a control to the "panelWpf" container. Below is the code from this file. "WpfControlLibrary31" is my WPF control library project, and "TestControl31" is the WPF control itself. Lastly, "WpfTest" is the name of the wrapper WinForms User control.
After building the WinForms control library, it appeared in the main UI project's Toolbox, and I was able to add it to the form like any other Windows Forms control. The next steps will be to add event handlers, getters, setters, etc. to the control for the needed interaction.
using System;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
namespace WinFormsLibrary
{
public partial class WpfTest : UserControl
{
// ElementHost for the WPF control
private ElementHost host = new ElementHost();
// WPF control to be hosted
private WpfControlLibrary31.TestControl31 uc = new WpfControlLibrary31.TestControl31();
public WpfTest()
{
InitializeComponent();
}
private void WpfTest_Load(object sender, EventArgs e)
{
// set the docking style for the ElementHost
host.Dock = DockStyle.Fill;
// add the WPF control as a child of ElementHost
host.Child = uc;
// add the ElementHost as a control of the panel container
panelWpf.Controls.Add(host);
}
}
}
Thoughts:
Some may wonder why I used the panel container. And in this simple experiment it was overkill; I could have simply docked the ElementHost to the control itself. However, if the WinForms User control has a more complex design, then the panel will be a placeholder while still allowing use of the Designer. Also, if a border or similar design is needed around the WPF control, then this should be possible with the panel.
Having the ElementHost and WPF control object as global allows access from all the control's methods, obviously, just like any controls added in the Designer itself.
The WPF control to host does not need to be in a dedicated WPF control library project. If it is a pre-existing WPF control (e.g. MediaElement), then use it for the global WPF object.
This WinForms control library is what I have been needing to consolidate and improve efficiency of my custom controls. So this issue with the .NET Core WinForms Designer turned out to be a blessing in disguise.
What are your thoughts? Thanks for the brainstorming help!
Is there a way to automatically generate XAML code when you drop your control from toolbox to designer? I.e. it would create certain objects (nested properties) automatically and user would not have to type the same code every time to set certain (nested) properties. Kind of a template XAML code that is pre-defined by control's developer.
I'm pretty new to WPF so I'm wondering why there aren't any nested properties in the controls that are in Visual Studio's toolbox (button, label etc...)? Are attached properties a cure for this or have they just cut corners when designing WPF. :)
The problem is that my control (WinForms style property hierarchy) has nested properties and if I "internally" in my code create objects for those properties then XAML does not reflect the situation because it does not have any elements that match the current situation (i.e. the objects created in my control's constructor).
Is the only solution to leave all the properties null and let the user create them all? That way it seems to work correctly but user has to write many lines of XAML to reflect the situation in WinForms.
The functionality that you seek is not available via any of the controls in WPF. However, Visual Studio used to have Macros that would enable us to add pre-written sections of code into our pages, but unfortunately, they decided to remove that great functionality. Fortunately, they have introduced Code Snippets as a partial alternative.
Unfortunately again, these Code Snippets don't work in XAML pages, but once again fortunately, there are a few Visual Studio add ins that will enable you to enter pre-written XAML into your pages at the click of a button on the Code Plex website:
XAML Code Snippets addin for Visual Studio 2010
XAML Snippets for Visual Studio
Please try using one of the above add ins to see if they meet your needs.
I am currently following this tutorial
http://channel9.msdn.com/Series/KinectQuickstart/Setting-up-your-Development-Environment
But at around 9:50 he uses a component called KinectSensorChooser which is not available anymore in the latest SDK 1.6 version because i read Microsoft's SDK History log that states
"We’ve taken KinectSensorChooser, formerly part of the WpfViewers and split the logic and UI into two different classes: KinectSensorChooser and KinectSensorChooserUI in Microsoft.Kinect.Toolkit.dll.
KinectSensorChooser could be used in non-WPF scenarios as it is logic only, no UI."
Source: http://www.windows7download.com/win7-kinect-sdk/history-lxqvgakz.html
Since the Microsoft.Kinect does not include the KinectSensorChooser component i added the Microsoft.Kinect.Toolkit reusable component which does include the KinectSensorChooser but the component is not showing up in the toolbox, i tried adding it manually by right clicking on the toolbox and selecting choose items then WPF components then locating it but it imports as a UI (KinectSensorChooserUI) and if i drag it onto the form the component disappears from the toolbox, i am using Visual Studio 2012 Ultimate on Windows 8
I've never added the KinectSensorChooserUI control to the toolbox in Visual Studio. The need to do so really isn't there.
If you feel obligated to do so, I found a Adding Your WPF Control To The Toolbox blog post that might be of use. Haven't tried it myself, so I can not promise it will work.
I personally do not use the UI component of the KinectSensorChooser. Unless you really plan to be turning the Kinect on/off or switching between multiple Kinects manually, it doesn't really serve much of a purpose. It does provide some feedback, but that can done in other more aesthetically pleasing ways.
To use the KinectSensorChooser you simple need the following in your main class:
private readonly KinectSensorChooser _sensorChooser = new KinectSensorChooser();
public MainViewModel()
{
// other initialization here
_sensorChooser.Start();
// more initialization here
}
You now have an active KinectSensorChooser, just minus the UI.
If you are dedicated to using the UI component, forgo trying to add it to the toolbox and just do the following:
Add the Toolkit project or a reference to the .dll.
Add the namespace to your Xaml so that you can reference the controls in your markup. xmlns:kt="clr-namespace:Microsoft.Kinect.Toolkit;assembly=Microsoft.Kinect.Toolkit"
Add the control to your visual tree
<kt:KinectSensorChooserUI x:Name="SensorChooserUI" />
Your code behind would declare the namespace, initialize the KinectSensorChooser and set up any events you want.
using Microsoft.Kinect;
using Microsoft.Kinect.Toolkit;
private readonly KinectSensorChooser _sensorChooser = new KinectSensorChooser();
// somewhere in your constructor, or other init function
this.SensorChooserUI.KinectSensorChooser = _sensorChooser;
_sensorChooser.Start();
I have been trying to customize a webbrowser control in wp7. All I need to do is to add a border property(I think it is already available in webbrowser but I have to make it mandatory when I make it as a control) and want to add a few extra event handlers and make it as a control so that it can be used later in different projects.
I tried reading through materials in msdn for writing control template and it all revolves around writing a few xaml code and attaching it with codebehind to make it work. What I don't understand is how do I learn xaml? or in other words where is the reference for all the tags that msdn talks about in xaml? Itseems to be huge and I am not sure how to go about it. The tutorial in msdn straight away divulges into xaml code and I am totally confused..
So now all I am trying to do is this,
create a control in Expression Blend (Windows Phone Control Library) that would create a class (MyCustomControl) that inherits
from CustomControl base class.
Now in xaml I am adding a webbrowser control and adding four event handlers (mouseup,down etc.,).
I build this control in blend and add the corresponding dll in VS2010.
And now once I try to add this control to my wp7 phone application it says "Cannot create an instance of MyCustomControl"..
These were further links that I referenced in creating one,
Windowsphone - Creating a custom control
Windowsphone - Control Template.
UserControl vs Custom Control
Creating a new control by creating ControlTemplate
Any further help would be great.
There is no definitive list of 'elements' you can add to your XAML. The reason for this is that the XAML parser can create any class which is a UIElement based on the XML you provide. So the elements available to you depend on the assemblies present in your project. Read teh MSDN XAML Overview for details
For a list of controls that are present by default, take a look at the System.Windows.Controls namespace (I think this link is not for your version of Silverlight, it might be best to use the Object Browser to look at the assemblies in your project).
For your problem, where you want to add a border to a WebBrowser control. I would recommend creating a UserControl as per this tutorial.
In this scenario I have a base component with a close button and a flow panel; (FlowLayoutPanel) the idea being that components extending this add their controls to the flow panel and will have the close button functionality done for them.
The problem is that I can't seem to persuade VS to add the components in the subclassed component to the flow panel; this ends up with me having to do so in the code. Which is all well and good except that it won't show up in the designer view. If I add it to the partial class with the designer generated code then I can see the controls in the designer view laid out by the flow panel. But this just gets overwritten afterwards.
Visual Studio doesn't seem to let you dock controls in inherited panels - unless I'm doing something wrong? I did make sure that the base panel is publically visible in case this was the issue.
--
An alternative might be some way to persuade the designer to execute/not overwrite my code in the designer class.
You need to make a ControlDesigner for your control and override the InternalControlDesigner and GetParentForComponent methods.
For an example, open System.Windows.Forms.Design.SplitContainerDesigner (in System.Design.dll in Reflector.