Windows Forms Designer Code modifies user control collections and objects - winforms

VS 2010, Windows 7: Windows Forms - I have a number of forms that contain user controls that reference domain model objects. Some of the controls reference single objects and some reference collections of domain model objects. When I open the project or individual forms, the IDE will check out the forms and add dummy domain model objects. In some cases, this has no serious side effects and in others this result in the app crashing. Why is this happening and how do I prevent this from happening in the future? I would like to get to the point where the designer doesn't add anything extraneous - I can crash the system on my thank you very much. Thanks.

The designer will create a default instance for each public property contained in child user-controls in the current control it is displaying. This can be changed using the DesignerSerializationVisibilityAttribute setting the visibility to DesignerSerializationVisibility.Hidden.
This tells the designer to leave those properties alone.
You will likely have to go through the designer file itself and remove the old allocations and assignments for the properties you marked.

Related

Create users for a WPF application

I'm creating an application on which I want different users to use it. I want to insert a variable, only modifiable at development mode. I think maybe there should be a way of using the App.Settings of the WPF Application, but, after one hour googling, I don't have a clear idea yet.
So, I need:
A variable that makes the WPF Application run at administration or client scope
If I have that variable in a specific role, I want to disable some controls
Any idea on where to look for a solution for this?
Well you could add to the base class of your ViewModels a property which contains the value reflecting the mode. As next step you could bind the IsEnabled property of the controls, which shall have this behavior, on this property of their related ViewModel.
Since you don't want to provide different modes with different states a.s.o., this seems to be the best approach.

Programmatically get XAML of an FrameworkElement in SL4

I tried to serialize a FrameworkElement with DavidPoll's XamlSerializer, but I get a totally different result than the (right) one that I get with Silverlight Spy. For example with XamlSerializer I get alot of empty tags(like MatrixTransform, ScrollViewer etc.) but not the ContentPresenter node that I get with Silverlight Spy. Any idea how to get a clean logical tree at runtime?
Update: I have a form designer program that stores those forms in a DB and at runtime it creates objects (user controls) from that info stored in a DB. Each form is composed of some fields. At runtime it programmatically creats an UserControl that contains all fields. I would like to get the generated XAML, just like I can get it with Silverlight Spy.
edit: I'm not limited to Silverlight environment, a soltion for a desktop application is valid too.
Short answer is: I don't think you can from within Silverlight itself. Sorry.
Once the XAML has been parsed and loaded into framework elements you have already lost information. For instance regenerating a path from the in memory object is non-trivial and you won't have access to the internals of the path element from Silverlight code.
Silverlight Spy adds back information that a simple XamlSerializer won't generate. Silverlight Spy has no limitations as it is a "real" desktop application, with full operating system access, whereas you want to actually do this in Silverlight itself which is very restricted sandbox environment (for security reasons).

Silverlight 4 + Prism create controls at runtime

I'm creating a Silverlight 4 application to manage active directory objects (CRUD Users, groups etc). Now we all know that active directory objects have lots of properties.
I want to save some groups of property names in an SQL DB (ie, samaccountname, mail, etc.) for certain AD object types (users, groups, etc).
When a user in the silverlight app clicks on "create user" I want to
get all the property names I defined in the sql db for the user
create a pre defined silverlight control for each property and add it to the current "create view"
be able to read all the values the user enters in the controls and pass them on
The user controls differ depending on the type of the Active Directory property, i.e. for a property with a datetime value, we will create a user control with a calendar. This way we can keep the "Create" Views dynamic.
The Silverlight / Prism foundation is already there and I'm adding my Views via the RegionManager. It all works just fine but I'm not sure how to add controls in such a dynamic way that it still works with PRISM and the MVVM pattern. Thank you for any input.
I'm going to assume that your comfortable with the getting the properties from the db and saving the values back and focus on the middle area of creating the view with MVVM in mind.
The PRISM part I wouldn't worry about. You say you've got the views registered with the region manager and that's about all you need to do.
My initial thought was how would you "create" controls at runtime with MVVM considered. Creating controls is not the hard part but would require a handle on the element you will be injecting these into, a root grid for example. This would on the surface feel very un-MVVM. Personally I think it's valid to have "view" code done the old fashion way, it's the "data" code used in binding that should be MVVM'd. The issue is telling the code that will inject the controls on to the view what to actually inject. I can't think of a neat way to do this.
As a solution could you not create a view containing all the controls that apply to each of the properties and rather than "create" them when needed "hide" them when not needed? You could bind the "Visibility" property (probably through a value converter) to a property in the ViewModel that can be used to determine if that particular control should be shown or not. If these where placed in a stack panel then the view would dynamically shrink.
If you think a code example would help let me know.

How does the Winforms Designer instantiate my form?

I'm developing my own WinForms designer. It must be able to load existing custom form types. One of the issues I hit is forms without a default ctor: My code currently instantiates the form before it can load it into the designer, which requires a default ctor.
OTOH, VS2008 is able to load such forms. I believe it doesn't actually instantiate my form (as noted in this question): Even default ctors are not executed. And it doesn't truly execute InitializeComponent(). I just added a messagebox in that function and it doesn't show.
It looks like it dynamically mimic the custom form type and executes only parts of the code in InitializeComponent which it thinks is relevant.
Does anyone know where I can find more information regarding how the VS designer works.
TIA.
Note: I found this related question without satisfying answers
EDIT: Additional info: Steve points me to CodeDom, which is very insteresting. My problem though is that the types I need to load into my designer are already compiled instead of being available as source code. I can't find any way to apply CodeDom deserialization to compiled code.
Found this here:
When you open a new Windows
Application project in VS, you see an
empty form called Form1 in design
view. Now, you haven't built the
project yet, so how is the designer
able to create an instance of Form1
and show it? Well, the designer is not
really instantiating Form1 at all. It
is creating an instance of the base
class of Form1, i.e.,
System.Windows.Forms.Form. With a
basic knowledge of object oriented
programming, you will find that this
intuitively makes sense. When you are
designing Form1, you start with the
base class, Form, and customize it.
This is exactly what the designer
helps you to do.
Now let's say you added a bunch of
controls to the Form and closed the
designer. When you reopen the
designer, the controls are still
there. However, the base class Form
doesn't have these controls on it, so
if the designer isn't running the
constructor of Form1, how did it show
the controls? The designer does this
by deserializing the code in
InitializeComponent. Each language
that the designer supports has a
CodeDomProvider that is responsible
for providing a parser that parses the
code in InitializeComponent and
creates a CodeDom representation of
it. The designer then invokes a set of
CodeDomSerializers to deserialize this
into actual Controls (or more broadly,
Components) that it can add to the
design time Form. Now, I have glossed
over a lot of details in that
description, but the point here is
that Form1's constructor and
InitializeComponent are never really
invoked. Instead, the designer parses
the statements in InitializeComponent
to figure out what controls to
instantiate and add to the form.
The above is how Windows Forms designer in Visual Studio loads a form. If what you are looking for is a way to create an instance of a form that has no default constructor and still have access to the contained components/controls, I'm not aware of a solution. The only method I'm aware of that allows you to bypass the lack of a default constructor is FormatterServices.GetUninitializedObject, but beware ...
Because the new instance of the object
is initialized to zero and no
constructors are run, the object might
not represent a state that is regarded
as valid by that object.
I too have an app that requires instantiating compiled forms but have always used Activator.CreateInstance and required other developers to include, at the very least, a private default constructor if they want their form accessible in my app. Since we own the entire codebase and everyone is aware of the requirement, this isn't a problem and works out well for us.
As an addition to Steve's answer, if you add a new Windows Form to a project, but make it abstract, you can still open it in the designer. However, if you add another form, and have it derive from the first (abstract) form, you get an error when attempting to open the form in the designer.

How do I get the Localizable property and support in my own design tool?

Overview
In another question, I asked about deploying localizations for some runtime compiled UserControl's. However, before I can get to deploying the localizations, I need a way of localizing the controls.
Background
The controls are created by our own WinForms-style designer (using .NET's support for design surfaces, etc.) and saved as a binary format that combines the CodeCompileUnit, resource resx, and user source into one file. These files are then compiled into an assembly as appropriate at runtime by another tool.
In order to localize these, we need to tell the designer and serialization that localizable property values are to be stored in the resources. The VisualStudio WinForms designer does this using an extension property called Localizable and an associated property for specifying the default culture. We need this property in our custom designer, if possible.
Constraints
We need our standalone designer tool that is easy to use for non-developer types as well as restricting certain actions so using a free edition of Visual Studio (i.e. C# Express) is not going to work (I've already pitched it and failed); therefore, any solution to how we localize these UserControl's needs to compensate for this.
Question
Can we get the Localizable support into our custom WinForms designer?
If yes, how?
If no, what alternatives are there to localizing our UserControl's? e.g. post-processing somehow, different file format, etc.
I'm not sure if I understood your question correctly.
Just check for the System.ComponentModel.LocalizableAttribute on all properties to (de-)serialize if your control is Localizable.
// Gets the attributes for the property.
AttributeCollection attributes =
TypeDescriptor.GetProperties(this)["MyProperty"].Attributes;
// Checks to see if the property needs to be localized.
LocalizableAttribute myAttribute =
(LocalizableAttribute)attributes[typeof(LocalizableAttribute)];
if(myAttribute.IsLocalizable) {
// Insert code for handling resource files here.
}
Since you decided to write your own designer you have to do this yourself.
You need to add a System.ComponentModel.Design.LocalizationExtenderProvider to your design surface.

Resources