When I load solution and there is an opened designer tab for some window, then this window static constructor is not executed.
Perhaps my conclusion is wrong (because I am absolutely clueless how designer load things), but here is a test case:
Create new WPF project.
Create simple extension
public class MyExtension : MarkupExtension
{
public static bool Test;
public override object ProvideValue(IServiceProvider serviceProvider) => Test.ToString();
}
Add to main window
<TextBlock Text="{local:My}" />
and
static MainWindow()
{
MyExtension.Test = true;
}
Now compile it (F6), TextBlock should show True in designer.
Do not close designer window. Close VS.
Start solution (double-click sln file).
As soon as designer loads window you will see TextBlock display False.
WTF? Can someone confirm that (or is it my VS 2015 bug)?
I would really like to know how designer works: how window is loaded, which events/methods are used, etc. It seems window constructor (non-static one) is not executed (anything put there is not happening in design time), how is the window then created and displayed?
I know how it works for Visual Studio 2010 and reading your question I suppose that the same principles may be also applied to Visual Studio 2015.
When a control is rendered inside the XAML designer (regarding VS2010 it is called Cider ) as the main control (i.e. a Window) its constructor is not run. On the other side, if a control is a child of another control which is rendered inside the XAML designer, the first control's constructor is executed (i.e. a UserControl inside a Window). You can read more about it here.
So you need to move the My.Test initialization into a customized control, for example:
public class MyTextBlock : TextBlock
{
static MyTextBlock()
{
MyExtension.Test = true;
}
}
Then use it inside your Window:
<local:MyTextBlock Text="{local:My}" />
After you compile your project, you will see the "True" text in the designer. I repeat: it works for Visual Studio 2010, so I hope it can represent an hint to solve your issue.
Related
I am developing a C# Windows Form project with Visual Studio 2019. I have inherited a new control, called NewGroupBox, from System.Windows.Forms.GroupBox, the control is under name space MyProject.NewCtrls and was added through the standard procedure How to: Inherit from Existing Windows Forms Controls. I did not do any change on the code generated except changing public partial class NewGroupBox: Control to public partial class NewGroupBox: GroupBox
In the main frame, I have a GroupBox object called groupbox_Table.
groupBox_Table = new System.Windows.Forms.GroupBox();
The form designer could open normal. However, if I manually changed GroupBox with NewGroupBox
groupBox_Table = new MyProject.NewCtrls.NewGroupBox();
The form designer cannot be opened properly. The error message shows "Could not find type 'MyProject.NewCtrls.NewGroupBox' ...". Of course the type is defined in my project and there is no error when building the project.
How do I fix this problem so that form designer can open normally? Thanks a lot!
So basically I add this code to my Form1.Designer.cs:
this.comboBox1.Items.AddRange(Enumerable.Range(0, 30).Cast<object>().ToArray());
which requires adding using System.Linq; on top of namespace WindowsFormsApp. The program runs just fine, the only thing is that when I go back to the Form1.cs[Design] GUI part, Visual Studio returns me the following error: To prevent possible data loss before loading the designer, the following errors must be resolved.
I can ignore that and the program works just fine, but it kinda worry me. Is there maybe another way to add the using System.Linq; line without making VS get angry at you?
There is no reason to modify your designer generated code. Just put your line of code in your Forms constructor, after the line/region that is already there.
I suppose Visual Studio rewrites your file and removes the using. Try changing your code to
...System.Linq.Enumerable.Range(0, 30)...
That said. You shouldn't add code to the desinger file on any other place as in the default constructor (if present) after the call to InitializeComponent() or inside a protected virtual void Dispose(bool disposing) function (if present).
And even then you should move the constructor or dispose function to your form1.cs file.
If you want to add items to your combobox do this via the property grid and let visual studio take core about writing the designer file or do it in the appropriate event handler (I would suggest either load or shown event).
The InitializeComponent wouldn't be the right place for modifing controls, since the next time you open the form in the designer the items are added to the combobox and get serialized during save unless your write
public Form1()
{
InitializeComponent();
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
if(!designMode)
{
this.comboBox1.Items.AddRange(Enumerable.Range(0, 30).Cast<object>().ToArray());
}
}
I am currently using windows forms application in visual studio. I want to change button and textbox properties programmatically and not use the the properties tab. How do i do this? Is there a way to access the code of the UI of that button/Textbox after it is changed in the properties tab?
Of course you can change that programmatically. If you have for example a button called btnStart, then you have in your form access to all properties:
btnStart.Text = "start";
Have also a look at: Change properties of programmatically created buttons
EDIT:
If you change it programmatically after the InitializeComponent(); it will override changed properties set manually in the properties tab.
Yes. And in fact it's always done in code -- Properties window (i.e. VS winforms designer) just writes some code for you. You can see that code when you delve into the InitializaComponent() method call in the form's constructor (right click InitializeComporent and select "Go to definition").
Anytime after this InitializeComponent() call, you can add code to change what you want:
public Form1()
{
InitializeComponent();
button1.Text = "Go!";
}
I made a reuseable control for our little team in WPF: a simple Dialog, that we use often.
The handling of the window is done in a private method:
private static void ExecuteInternal(
Window owner,
string windowTitle,
string label,
object operation,
MyDialogSettings settings)
{
MyDialog dialog = new MyDialog(windowTitle, settings);
dialog.Owner = owner;
dialog.Label = label;
ShowDialog();
}
The public call has a System.Windows.Window as parameter (--> WPF Window) and my function sets the Owner to this window.
Now my colleage wants to use this Window from a Windows Forms application.
My first thought was to overload the public function call with a form and then handle it with the WindowInteropHelper internally (see: http://blogs.msdn.com/b/mhendersblog/archive/2005/10/04/476921.aspx)
But I then would have to reference Windows.Forms in every (WPF)-Project that uses my library.
Because I cannot access the window instance from outside the WindowInteropHelper-thing cannot done in the Forms application.
Any ideas?
The problem I see with this approach is that the reusable control is not reusable at all. As you note, the main method uses WPF-only types that cannot be used anywhere else, so reusage on WinForms is not possible as it stands now.
To be able to do so you would need to extract the main logic and visuals of the dialog window into an user control (so it can be hosted in WinForms). This is the first thing I would do:
<UserControl .......>
<Grid>
<!-- Other controls you have on the dialog -->
<Button Content="Accept"/>
</Grid>
</UserControl>
Pretty easy, just move all the content to an user control. Then the window itself becomes trivial by just including this control:
<Window .......>
<controls:MyDialogContent ..../>
</Window>
So far nothing changes, and the method you posted is works exactly the same as before. We'll leave it as being WPF-only and in turn implement an almost-equal method for WinForms.
On the WinForms project, now you have to create the form that will take the place of MyDialog. This form can be as simple as the WPF version, just an ElementHost that will contain the UserControl that you separated previously, with maybe any properties/methods needed for your logic.
The last part is to provide a WinForms method to call it, akin to the WPF one. This could be as simple as something like this:
private static void ExecuteInternal(Form owner,
string windowTitle,
string label,
object operation,
MyDialogSettings settings)
{
MyDialogForm dialog = new MyDialogForm(windowTitle, settings);
dialog.Owner = owner;
dialog.Label = label;
dialog.ShowDialog();
}
I have an extensibility project in Visual Studio and I need to use the event triggered when I change from one window to another in the visual studio editor, my problem:
I created a Tool Window that display some diagram, that diagram depend of an editable file, when I save the editable file my tool window updates the information, but when there is more than one editable file opened and I switch between them I want that the tool window updates the information as well. So:
I want to get the event triggered when I switch between windows, file or documents in Visual Studio so I can use it to execute the update code of my tool window. Is there something I can do about it?
I just read this question here but I didn't find a solution in there:
Are there any document window focus events?
You can subscribe to the EnvDTE.WindowEvents.WindowActivated event:
using EnvDTE;
using Microsoft.VisualStudio.Shell;
private class MyClass
{
private DTE dte;
public MyClass()
{
dte = Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
dte.Events.WindowEvents.WindowActivated += OnWindowActivated;
}
private void OnWindowActivated(Window gotFocus, Window lostFocus)
{
throw new NotImplementedException();
}
}
See for example the 1. Display document path of the active window in the status bar sample code.