Im new in Wpf C# programming and have maybe a stupid question.
I have a form and I need to create some controls with dynamic names.
(For Ex.: Grid: 'main' Controls: "str"+(int)i)
And I need to set Property Margin of this Controls OnTick.
So, Ik how to add this Controls, but have some problems in changing their properties.
Some code:
Image img = new Image();
img.Source = new BitmapImage(new Uri("pack://application:,,,/Resources/img.png"));
img.Name = "str_" + i;
img.Margin = new Thickness(-10,-10,0,0);
img.Width = 1;
img.Height = 2;
main.Children.Add(img);
// ToDo Something like this:
main["str_"+i].Margin = new Thickness(x,y,0,0);
So, the question is: How to Edit property of already Created Dynamic control?
Update.
I found it rather stupid to create tons of controls except of refreshing drawings.
Now I have no idea what is the best way of drawing bitmaps on form.
For example:
I have List of locations of bitmaps.
I need to update the
bitmap's locations 'x' times per second.
Look at the next solution. Here is the code that references to the properties of an existing controls by it's (control's) name. It changes the control's set of properties according to the set of properties you support in view model (or code behind). If you will be interested I can make the adaptation to achieve your set of requirements. Here is the link
WPF user control, access dependency properties of component elements .
regards,
Related
How i can make this buttons with icons like these ??
Normally, in order to create stylized buttons in Winforms, you have to work with the Button.Image property:
this.myButton.FlatStyle = FlatStyle.Flat;
this.myButton.Image = // your image
// ...
The buttons in your image include a text, but since the enumeration System.Windows.Forms.TextImageRelation (used in the property Button.TextImageRelation) does not allow for a text below the image... obtaining the same style with this approach risks to become a hard task (using GDI, handling painting events, creating a derivative of the Button class, etc...), unless there is a trick that I don't know.
The fastest and simplest way to recreate the same style is to create a button with empty Text property and manually include the text in the image file. Actually, you set:
this.myButton.FlatStyle = FlatStyle.Flat;
this.myButton.ImageAlign = ContentAlignment.MiddleCenter;
this.myButton.Text = "";
and you put this image (just an example) straight into the control:
This MSDN article offers some good advice about manually customising the form designer to improve performance:
Reduce the number of method and property calls on controls during startup. For example, Controls.Bounds is a better option than calls to Control.Location and Control.Size.
Create the form from the top down. In nested control hierarchies, set the parent property of containers (using the above rule) before adding controls to the container. As in the BigForm application, the panels had their parent property set to the form before the 40 controls were connected to the panel. If further containers exist lower in the hierarchy, the same changes should be applied.
I have followed the 1st bit of advice, replacing:
this.MyControl.Location = new System.Drawing.Point(5, 5);
this.MyControl.Size = new System.Drawing.Size(630, 90);
with:
this.MyControl.Bounds = new System.Drawing.Rectangle(5, 5, 630, 90);
This resulted in a super 20% (about 200ms) speed-up on one form. I'm trying to follow the 2nd bit of advice and not quite sure how to proceed. The Designer.cs file contains code like this:
this.Controls.Add(this.pnlHeader);
but not the code I was expecting (according to the example):
this.pnHeader.Parent = this; // Not in the Designer
The code this.Controls.Add(this.pnlHeader); appears at the bottom of InitializeComponent. Is the advice suggesting moving the code to the top or something else entirely?
EDIT #2
i found this msdn article which explain the issue as following:
Another method for improving performance is to initialize the controls
in the control tree top-down. For example, if you have a panel control
with many controls in it, create the panel first, and then add the
controls to the panel. Also, setting the parent property of the
control instead of adding to the Controls collection can improve
performance.
For example, consider adding a textbox to a panel's control collection:
Before optimization:
// Create a new panel and textbox control
Panel panel1 = new Panel();
TextBox textBox1 = new TextBox();
// Set the Text property of the TextBox control
textBox1.Text = "My Text";
// Add the TextBox to the Panel's control collection
panel1.Controls.Add(this.textBox1);
// Add the Panel to the Form's control collection
this.Controls.Add(panel1);
//... subsequent controls
Optimizing this code snippet using the top-down and parenting techniques results in the following snippet:
After optimization:
// Create a new panel and textbox control
Panel panel1 = new Panel();
TextBox textBox1 = new TextBox();
// set parents from top to down
this.panel1.Parent = this;
this.textBox1.Parent = this.panel1;
// Set properties of child control (cause repainting only once)
textBox1.Text = "My Text";
//... subsequent controls
This can make a big difference with a deeply nested control hierarchy.
Optimizing the code in the InitializeComponent method by creating
the controls top-down and re-parenting them resulted in a performance
improvement of about 50% over the default Forms Designer generated
code!
Following on from the answer from S.Serp here are some observations to be aware of:
Replacing Location and Size with Bounds resulted in an average boost of ~15% for form loading.
Replacing Controls.Add with Parent resulted in a further boost of ~5-10% (for an impressive total of ~20-25%).
As Sefe points out, manually editing the Designer.cs file is usually only appropriate where you are not making changes in the Designer very often. Any changes made in the Designer will overwrite your manual code. Be warned! This is not a disaster, you simply lose the boost. Either live with the slower form loading or redo the manual changes.
Be careful to put the Bounds call after setting Multiline = true; on TextBox controls (if enabled). If you set it before, your control will (unhelpfully) be resized to a single line.
Be careful with ensuring each child control has the parent set correctly! Open all forms in the Visual Studio Designer after manually editing InitializeComponent to see that everything is kosher...but don't edit anything otherwise your changes will be deleted.
The lines...
this.Controls.Add(this.pnlHeader);
...and...
this.pnHeader.Parent = this;
...are equivalent. The control trees they produce are identical. And you should not change the auto-generated code. Your changes will be overwritten the next time the designer writes its updates.
You usually don't have to worry about the designer-generated code. You can concentrate on your part and assume the designer is correct.
I'm trying to develop a game in Windows Phone. I'm a beginner using c# and xaml. In the xaml I've objects with the same properties only Tag property is different. What I want to do is to loop througth object tags and change for another object (image) if I find a specific tag.
I've tried some code, like this:
foreach(Image tag in img) //but it says:
foreach statement cannot operate on variables of type 'Windows.Ui.Xaml.Controls.Image' because 'Windows.Ui.Xaml.Controls.Image' does not contain a public definition for 'GetEnumerator'...
Since as a beginner you won't likely use MVVM and just leave everything in the View, what you can do is just cycle through the LayoutRoot. If you have other Panel in the layoutroot that contain images, you want to do it recursively:
MainPage()
{
DoSomethingToImages(LayoutRoot);
}
DoSomethingToImages(Panel panel)
{
foreach(Image img in panel.Children.Where(x=> x is Image))
{
DoSomething(img);
}
var panels = panel.Children.Where(x=> x is Panel);
if (panels.Count > 0)
{
foreach(Panel p in panels)
{
DoSomethingToImages(p);
}
}
}
On the other hand, this is obviously bad practice, and you would normally bind your images to your viewmodel. The only exception might be heavily customised user controls to make things work that'd be otherwise extremely time-consuming to work around with MVVM. (Note: I think that MVVM is not always necessary for custom controls, since many times all you want is some custom graphical behaviour, like a button that takes an Image Background for it's pressed state as well, and that stuff belongs to the view, but you can usually solve that with a dependency property in the view and some XAML tweaking. Also, separating the ViewModel for a custom control makes it a bit harder to copy it to another project if you put it inside your own project - you have to find the viewmodel as well! :) ).
Like others have said, you'll need a collection to loop through.
Personally, I like dictionaries.
Here's an example I think you might be able to modify for your own purposes.
This will enable you to "loop though object tags", however as HighCore mentioned, it's probably not "the right way" to do whatever you're ultimately trying to accomplish.
Image img1 = new Image();
Image img2 = new Image();
Image img3 = new Image();
img1.Tag = "tag1";
img2.Tag = "tag2";
img3.Tag = "tag3";
Dictionary<string, Image> ImgDictionary = new Dictionary<string, Image>();
ImgDictionary.Add(img1.Tag.ToString(), img1);
ImgDictionary.Add(img2.Tag.ToString(), img2);
ImgDictionary.Add(img3.Tag.ToString(), img3);
foreach (KeyValuePair<string, Image> i in ImgDictionary)
{
// do stuff with i.Value or i.Key
}
string tmp_TagName = "tag1";
if (ImgDictionary.ContainsKey(tmp_TagName))
{
Image ReturnImage;
ImgDictionary.TryGetValue(tmp_TagName, out ReturnImage);
// do something with your ReturnImage...
}
I get this response from a web service call. Something like this
<Response>
<Control1 type = "DropdownList" value= "USA,UK,Sweden,UAE"/>
<Control2 type = "Textbox" value= "Contries"/>
<Control3 type = "Button" value= "None">
</Response>
Based on this I de-serialize it into List<Controls>.
Now I need to be able to dynamically create a winform based on these controls. My problem is the layout. I want to be able to create them nicely separated (If possible vertically aligned) in batches of lets say 5.So If I need 15 controls I have 3 columns and 5 rows.
What would be best way to achieve this? I know that I can use the inbuilt positioning properties like top, width etc., but maybe someone out there has done something similar in a better way.
I think you should use TableLayoutPanel. Also you can read best practices to use this control.
One benefit of using TableLayoutPanel from above article:
Layouts that will be modified or generated dynamically at run time, such as data entry forms that have user-customizable fields added or subtracted based on preferences.
So basically I am gonna do something like this(might be useful for someone else)
Form op = new Form();
FlowLayoutPanel panel = new FlowLayoutPanel();
op.Controls.Add(panel);
for (int i = 0; i < 10; i++)
{
Button b = new Button();
b.Text = "Button" + i.ToString();
panel.Controls.Add(b);
}
I have a complex Windows Forms GUI program that has a lot of automated control generation and manipulation. One thing that I need to be able to do is add a custom UserControl to a newly instatiated TabPage. However, when my code does this I get automatic resizing events that cause the formatting to get ugly. Without detailing all of the different Containers that could possibly be involved, the basic issue is this:
At a certain point in the code I create a new tab page:
TabPage tempTabPage = new TabPage("A New Tab Page");
Then I set it to a certain size that I want it to maintain:
tempTabPage.Width = 1008;
tempTabPage.Height = 621;
Then I add it to a TabControl:
tabControl.TabPages.Add(tempTabPage);
Then I create a user control that I want to appear in the newly added TabPage:
CustomView customView = new CustomView("A new custom control");
Here is where the problem comes in. At this point both the tempTabPage and the customView are the same size with no padding or margin and they are the size I want them to be. I now try to add this new custom UserControl to the tab page like this:
tempTabPage.Controls.Add(customView);
When making this call the customView and it's children controls get resized to be larger and so parts of the customView are hidden.
Can anyone give me any direction on what to look for or what could be causing this kind of issue?
Thanks ahead of time.
The UserControl's "AutoScaleMode" property should be set to "None".
If you want the customView to fill the TabPage.
Use Dock like this:
tempTabPage.Controls.Add(customView);
customView.Dock = DockStyle.Fill;
Then the customView will fill out the space in the TabPage, but you have to handle resizing of the customView so child controls will be shown properly.
I had the same issue.
The UserControl's "AutoScaleMode" set to "None" works for me.