How to align subviews in center with Xamarin iOS Fluent Layout? - c#

My code is like this:
var nameTextField = new UITextField();
var passwordTextField = new UITextField();
var loginButton = new UIButton();
//Bindings with MvvmCross...
Add(nameTextField);
Add(passwordTextField);
Add(loginButton);
View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
View.AddConstraints(
nameTextField.AtTopOf(View, 10),
nameTextField.AtLeftOf(View, 10),
nameTextField.AtRightOf(View, 10),
passwordTextField.Below(nameTextField, 10),
passwordTextField.WithSameLeft(nameTextField),
passwordTextField.WithSameRight(nameTextField),
loginButton.Below(passwordTextField, 30),
loginButton.WithSameLeft(passwordTextField),
loginButton.WithSameRight(passwordTextField)
);
With "nameTextField.AtTopOf(view, 10), the form is displayed on the top screen. But now, I need to align vertically all the controls (name, password and button) in the View.
How can I do this?
I already tried to sum the height with the margins of all controls and use .WithCenterY(View).Minus(value), but I think that's not the best way, especially when I have many controls.
Thanks.

First, create a subview to add all the form controls:
var formView = new UIView();
formView.AddSubviews(nameTextField, passwordTextField, loginButton);
Create constraints for those elements within the formView view:
formView.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
formView.AddConstraints(
nameTextField.AtTopOf(formView, 10),
nameTextField.AtLeftOf(formView, 10),
nameTextField.AtRightOf(formView, 10),
passwordTextField.Below(nameTextField, 10),
passwordTextField.WithSameLeft(nameTextField),
passwordTextField.WithSameRight(nameTextField),
loginButton.Below(passwordTextField, 30),
loginButton.WithSameLeft(passwordTextField),
loginButton.WithSameRight(passwordTextField)
);
Create constraints to center formView on screen:
View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
View.AddConstraints(
formView.WidthOf(View),
formView.WithSameCenterY(View);
...
);
I didn´t test any of this code, so it´s probably wrong at some point, but you get the idea...

Related

C# Windows Forms glitch while creating a control

I somehow noticed, that while I'm creating a control in my application, it first appears as weird rectangle and then it "shrinks" to it's correct form.
First thing you'll see after creation
Correctly created object
My question is, why I first see the rectangle in top left corner and then it suddenly changes to it's correct form. It's like split second thing (I had to use Thread.Sleep 'cos it's impossible to screenshot it), but my eyes can still see this and I'm really triggered when it's happening.
This is the code, where I'm creating the control:
var label = new Label
{
AutoSize = true,
TextAlign = ContentAlignment.MiddleLeft,
Font = new Font("Courier New", 9F, FontStyle.Regular,
GraphicsUnit.Point, 238),
Text = keyword,
Margin = new Padding(0, 6, 25, 3),
Padding = new Padding(0, 3, 0, 0)
};
var button = new Button
{
BackgroundImage = Image.FromFile("../../../Images/cross_200x200.png"),
BackgroundImageLayout = ImageLayout.Stretch,
Dock = DockStyle.Right,
Width = 21,
Height = 21,
FlatStyle = FlatStyle.Flat,
};
button.FlatAppearance.BorderSize = 0;
var pan = new Panel
{
AutoSize = true,
Padding = new Padding(0, 0, 1, 1),
BackColor = Color.PowderBlue,
BorderStyle = BorderStyle.FixedSingle,
Tag = keyword
};
button.Click += delegate
{
_keywords.Remove(pan.Controls.OfType<Label>().First().Text);
pan.Dispose();
StatusLabel.Text = $#"Removed {keyword}";
};
pan.Controls.Add(label);
pan.Controls.Add(button);
FlowLayoutPanelMain.Controls.Add(pan);
Everytime a "keyword" is added to FlowLayoutPanel control, at first it's a rectangle in top left corner and immediately after that it's fine.
With help from a friend of mine, we figured out, that this is happening due to Windows Forms old technology (It's probably not happening in .NET Core's WPF) and it's inability of creating controls at runtime. So, the offered solution for this seems to be just .Hide() the control, .Add() it to the FlowLayoutPanel and then simply .Show() it back, now my eyes will be satisfied.
...
pan.Hide();
FlowLayoutPanelMain.Controls.Add(pan);
pan.Show();
...
Try to remove AutoSize property and assign a new Size() to the panel
AutoSize = false,
Worked for me

(ListView?)-Control like in Windows Explorer

I'm wondering if there is any way to make a control like that one in windows explorer's auto start when you plugin a device.
I had thought that this could be a listview-control in a more or less modified way, but I was not able to find anything with Google. I also checked many CodeProject-pages.
Does anyone have an idea where I would be able to get the control or how I could make one myself? (I am not that good with OwnerDraw :P)
Thanks.
Actually tweaking a ListView is not any easier than ownerDrawing it. Here is an example that shows, how simple it really is.
You just script one event (DrawItem) and you are done.
This piece of code assumes:
The LV's View is set to List
You have a suitable ImageList added to your form
You have the LV's ownerDraw set to true
You have added two columns to hold the text shown in the two labels
You have made the 1st column wide enough to hold the whole stuff that gets drawn
You have made the LV's FontSize as large as the Images' Height (say 32)
Assign the appropriate ImageIndex values to the LV's Items
private void listView1_DrawItem(object sender, DrawListViewItemEventArgs e)
{
Point point0 = new Point(e.Bounds.Left, e.Bounds.Top);
Point point1 = new Point(imageList1.ImageSize.Width + 10, e.Bounds.Top + 5);
Point point2 = new Point(imageList1.ImageSize.Width + 10, e.Bounds.Top + 25);
Size size = new Size(listView1.ClientRectangle.Width, e.Bounds.Height);
Rectangle R = new Rectangle(point0, size);
Font F1 = new Font(listView1.Font.FontFamily, 11f, FontStyle.Bold);
Font F2 = new Font(listView1.Font.FontFamily, 10f);
if (e.Item.Focused) e.Graphics.FillRectangle(Brushes.LightBlue, R);
else if (e.ItemIndex % 2 == 1) e.Graphics.FillRectangle(Brushes.GhostWhite, R);
e.Graphics.DrawImage(imageList1.Images[e.Item.ImageIndex], point0 );
e.Graphics.DrawString(e.Item.Text, F1, Brushes.Black, point1);
e.Graphics.DrawString(e.Item.SubItems[1].Text, F2, Brushes.Black, point2);
F1.Dispose(); F2.Dispose();
}
Note that I have hard-coded a few Colors to paint every other line and also the focused item. These colors really should use the respective System colors. These come to mind:
SolidBrush brush0 = new SolidBrush(SystemColors.ControlLight);
SolidBrush brush1 = new SolidBrush(SystemColors.Highlight);
I am using the Font that is assigned to the LV but with moderate sizes. Obviously more or less anything, especially the various offsets, can be configured to your liking. But using colors from the System.Colors collection is good way to stay in keeping with your users' Windows themes.

Ellipse not shown on the canvas in wpf application

I have a wpf user control , inside it i have put a canvas named VisualFeedback , now programmatically i add a eclipse using :
Ellipse ellipse = new Ellipse
{
Fill = new SolidColorBrush(Colors.Red),
Width = 5,
Height = 5,
Opacity = 1,
Margin = new Thickness(10, 10, 0, 0)
};
VisualFeedback.Children.Add(ellipse);
But it does not show up in the canvas of usercontrol which is in the mainwindows of the application .
Your code works for me - you're sure that you're not just missing it? - it's quite small.

how to get a labels width before it is rendered in WPF

Tricky one to explain this. I have a custom built properties grid. The left hand column has the property labels. Sometimes depending on the property, I want a little elipsis button to show the user that they can launch a dialog. I want the buttons to be inline vertically to make the UI look neat. The labels vary in width depending on the name of the property "onEnterPressed" or "upLink" for example.
If I add the elipses button alone and use a margin like so ...
elipsisButton.Margin = new Thickness(135, 0, 0, 0);
135 from the left is exactly where I want to place the button.
I was hoping to be able to do something like
Label newLabel = new System.Windows.Controls.Label();
newLabel.Content = anInfo;
aPanel.Children.Add(newLabel);
elipsisButton.Margin = new Thickness(135 - newLabel.Width, 0, 0, 0);
It would appear however, that the label doesn't get a width until it's been rendered on screen so I can't find out what size margin to add to my elipsis button. Any ideas?
You can call the Measure() method in order to ask the control the size it needs to be displayed:
var l = new Label() { Content = "Hello" };
l.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Size s = l.DesiredSize;
And then use the value of the DesiredSize property.

ToolStripMenuItem can't show checkmark and Image (icon) when RenderMode is "System"?

My Windows Forms application has a MenuStrip and some of the menu items (ToolStripMenuItem) have an icon (setting the ToolStripMenuItem.Image property).
When the RenderMode property of the MenuStrip is set to ToolStripRenderMode.System, the checkmark doesn't display when the Checked or CheckOnClick property is true and the menu item has an icon.
It does display when i switch the MenuStrip.RenderMode property to ToolStripRenderMode.Professional or ToolStripRenderMode.RenderManagerMode.
Unfortunately, this is a problem because my app requires:
A ProgressBar in marquee mode, so Application.EnableVisualStyles() is required to get this to work.
The app requires a "flat" visual style, which i accomplished by leaving out the call to Application.EnableVisualStyles() and leaving the default ToolStripRenderMode.RenderManagerMode on the MenuStrip. But then i can't get my marquee ProgressBar!
Setting the RenderMode to ToolStripRenderMode.System solves the look and feel requirement, but takes away the ability to have checked menu items w/icons.
Is there any way to satisfy all my requirements? Am i missing something? Thanks for looking.
Wow, i stumped SO! Now i know i must be working on some serious code.
Anyway, the answer is: implement your own ToolStripRenderer by creating a class that inherits from ToolStripSystemRenderer.
Override the methods that draw the items with your own code. Here's what i was looking for specifically that draws the checked item. It draws a check if there's no image for the ToolStripMenuItem.
protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
{
base.OnRenderItemCheck(e);
if (e.Item.Selected)
{
Rectangle rect = new Rectangle(3, 1, 20, 20);
Rectangle rect2 = new Rectangle(4, 2, 18, 18);
SolidBrush b = new SolidBrush(Color.FromArgb(49, 106, 197));
SolidBrush b2 = new SolidBrush(Color.Orange);
e.Graphics.FillRectangle(b, rect);
e.Graphics.FillRectangle(b2, rect2);
e.Graphics.DrawImage(e.Image, new Point(5, 3));
}
else
{
Rectangle rect = new Rectangle(3, 1, 20, 20);
Rectangle rect2 = new Rectangle(4, 2, 18, 18);
SolidBrush b = new SolidBrush(Color.FromArgb(49, 106, 197));
SolidBrush b2 = new SolidBrush(Color.Orange);
e.Graphics.FillRectangle(b, rect);
e.Graphics.FillRectangle(b2, rect2);
e.Graphics.DrawImage(e.Image, new Point(5, 3));
}
}
I did also come across a simpler alternative:
You can simply put your menu items into a ContextMenuStrip and then assign it to the DropDown property of the DropDownButton.
Hope this helps anyone out there who doesn't fancy overriding the Paint method.

Categories