I have a StackPanel with 2 children that I need to resize based on the StackPanels size. I attached an event handler to SizeChanged of the StackPanel and resize the element there. The problem is the event handler is fired again and again until the app crashes. What's the deal?
class BasicStatusTile : StackPanel {
private TextBlock TopText { get; set; }
private TextBlock BottomText { get; set; }
public BasicStatusTile() {
InitializeComponent();
}
private void InitializeComponent() {
TopText = new TextBlock() {
Text = "0",
HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Stretch,
TextAlignment = Windows.UI.Xaml.TextAlignment.Center,
FontSize = 48
};
BottomText = new TextBlock() {
Text = "Speed (km/h)",
HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Stretch,
VerticalAlignment = Windows.UI.Xaml.VerticalAlignment.Bottom,
TextAlignment = Windows.UI.Xaml.TextAlignment.Center
};
base.Children.Insert(0, TopText);
base.Children.Insert(1, BottomText);
base.Background = new SolidColorBrush(Colors.White);
base.SizeChanged += BasicStatusTile_SizeChanged;
}
private void BasicStatusTile_SizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs e) {
double third = base.ActualHeight / 6;
TopText.FontSize = third * 4;
BottomText.FontSize = third;
}
}
This happened because you change FontSize of TextBlock. It fires the sizechanged event of your custom StackPanel.
You should consider what kind of control you need.
What is your purpose of using custom stackpanel with sizechanged event?
Also, FontSize is not the same as a Height of TextBlock
Related
I created a changing_button with a background image. The FlatAppearance.BorderSize property of this button is zero, so normally it displays without a border. But if I make changing_button disabled, it will have a black border:
How can I remove this border?
I guess that the border appears because changing_button is in focus then I change its Enable property. For that reason, I tried to remove focus from the button and set changing_button.TabStop = false, but it didn't help.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace winforms_test_1
{
public partial class Form1 : Form
{
Button changing_button;
private readonly Image enable_img = Image.FromFile("D://images//enable_img.png");
private readonly Image disable_img = Image.FromFile("D://images//disable_img.png");
public Form1()
{
InitializeComponent();
TableLayoutPanel main_panel = new TableLayoutPanel
{
BackColor = Color.White,
Dock = DockStyle.Fill
};
CreateButton();
Controls.Add(changing_button);
}
private void CreateButton()
{
changing_button = new Button
{
BackgroundImage = enable_img,
BackgroundImageLayout = ImageLayout.Center,
TabIndex = 1,
TabStop = false,
FlatStyle = FlatStyle.Flat,
Margin = new Padding(10, 10, 0, 0),
Location = new Point(40, 40),
};
changing_button.FlatAppearance.BorderSize = 0;
changing_button.Size = new Size(80, 50);
changing_button.Click += new System.EventHandler(this.Button_Click);
}
void Button_Click(object sender, EventArgs e)
{
changing_button.BackgroundImage = disable_img;
changing_button.Enabled = false;
changing_button.TabStop = false;
}
}
}
enable_img.png:
disable_img.png:
To workaround this, I set the border size to 1.
Then set the border color to be the same color of BackColor. Just change on the click event to match the current state.
I am using Xamarin.Forms to add custom render to a button. I need to add a click event on CmButton without creating reference variable, or defining outside of the StackLayout.
Here is my code:
Content = new StackLayout
{
Children
{
new CmButton
{
Text = "SIGN UP| AGREE TO TERMS",
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BorderWidth = 0,
TextColor = Color.White
}
}
}
I want click event within the new Button{} block
Use Command instead of Click
var btn = new Button
{
Text = "",
Command = new Command(()=>
{
})
};
Use-
Button.Clicked += OnButtonClicked;
It will create a click event of button as-
void OnButtonClicked(object sender, EventArgs e)
{
}
For more detail:- https://channel9.msdn.com/Shows/Visual-Studio-Toolbox/VS-Toolbox-Xamarin-Forms
and https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/getting_started_with_xaml/
You have to assign your button to a variable to use events.
myButton = new CmButton
{
Text = "SIGN UP| AGREE TO TERMS",
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BorderWidth = 0,
TextColor = Color.White
}
Content = new StackLayout
{
Children
{
myButton
}
}
myButton.Clicked += (o, e) => {
//click event handler
};
I need to have a Custom Panel that acts as a Canvas but really is a ScrollViewer with a Canvas inside. The user should be able to add controls like in a canvas; I need the ScrollViewer wrapper to handle zoom and pan behaviours.
So, I started writing the control:
[ContentProperty("Children")]
public class MyContainer : ScrollViewer, IAddChild
{
private Canvas _innerCanvas;
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public UIElementCollection Children
{
get { return _innerCanvas.Children; }
}
public MyContainer()
{
this._innerCanvas = new Canvas();
this.Content = _innerCanvas;
_innerCanvas.Height = this.ActualHeight;
_innerCanvas.Width = this.ActualWidth;
}
void IAddChild.AddChild(object value)
{
_innerCanvas.Children.Add(value as UIElement);
}
void IAddChild.AddText(string text)
{
;
}
}
but it doesn't work. If I try to use it in XAML
<Controls:MyContainer>
<TextBlock Height="92" Canvas.Left="324" TextWrapping="Wrap" Text="TextBlock 1" Canvas.Top="267" Width="284"/>
<TextBlock Height="92" Canvas.Left="462" TextWrapping="Wrap" Text="TextBlock 1" Canvas.Top="267" Width="284"/>
</Controls:MyContainer>
the children aren't visible.
What is wrong?
You set the size of your canvas to ActualWidth and ActualHeight at the Ctor, but they are not yet initialized at that point. ActualWidth and ActualHeight are only meaningful when the control is presented on the screen. Try to subscribe to the Loaded event of the ScrollViewer, and change the Canvas size then:
public MyContainer()
{
this._innerCanvas = new Canvas();
this.Content = _innerCanvas;
this.Loaded += ScrollViewer_Loaded;
}
public void ScrollViewer_Loaded(object sender, EventArgs e)
{
_innerCanvas.Height = this.ActualHeight;
_innerCanvas.Width = this.ActualWidth;
}
I am using the TableLayoutPanel for example if I have 3 rows and 5 columns. I want to draw only the outer border for the entire panel. By default the the panel provides CellBorderStyle which adds all side borders to all the cells available. Is there any way where we can set only outside borders?
I have provided a sample code below.
TableLayoutPanel tblPanel = new TableLayoutPanel;
tblPanel.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
Label lblName;
TextBox txtName;
Button btnAdd;
int colCnt = 0;
for(int rw =0; rw < 3; rw++)
{
lblName = new Label();
lblName.Name = "mylabel" + rw.ToString();
tblPanel.Controls.Add(lblName, colCnt, rw);
colCnt++;
txtName = new TextBox();
txtName.Name = "mytext" + rw.ToString();
tblPanel.Controls.Add(txtName, colCnt, rw);
colCnt++;
btnAdd = new Button();
btnAdd.Name = "mybutton" + rw.ToString();
tblPanel.Controls.Add(btnAdd, colCnt, rw);
colCnt = 0;
}
TableLayoutPanel does in fact support the BorderStyle property, which is what you want. For example:
tableLayoutPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
https://msdn.microsoft.com/en-us/library/system.windows.forms.tablelayoutpanel.borderstyle(v=vs.110).aspx
It is decorated with:
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
So Intellisense won't show it to you, but it is documented and it works. I have no insight into why it is non-browsable.
You'd be better off painting the cell border yourself. Something along the following lines, then customize:
public TableForm() {
InitializeComponent();
this.tableLayoutPanel.CellPaint += tableLayoutPanel_CellPaint;
}
private void tableLayoutPanel_CellPaint(object sender, TableLayoutCellPaintEventArgs e) {
var topLeft = e.CellBounds.Location;
var topRight = new Point(e.CellBounds.Right, e.CellBounds.Top);
e.Graphics.DrawLine(Pens.Black, topLeft, topRight);
}
At design-time:
At runtime:
You can achieve by changing the property CellBorderStyle to Single or desired selection.
Property Change :
Sample :
TableLayOutPanel itself does not support a property for border except CellBorderStyle which is not what you want.
I suggest you to put your TableLayOutPanel into a Panel control and set Dock property of your TableLayOutPanel to Fill.
Then Set BorderStyle of Panel to what you want (FixedSingle or Fixed3D)
public TestForm()
{
InitializeComponent();
tableLayoutPanel.Paint += tableLayoutPanel_Paint;
}
private void tableLayoutPanel_Paint(object sender, PaintEventArgs e){
e.Graphics.DrawRectangle(new Pen(Color.Blue), e.ClipRectangle);
}
I have an application that gets one of its UI controls via an INativeHandleContract from a different AppDomain. When the size of the control changes the FrameworkElement in the host doesn't get an updated size. I was wondering if there was any way to fix this.
Here is the sample code (the XAML is just a blank window):
public partial class Window1 : Window
{
private StackPanel m_stackPanel;
private Expander m_expander;
private UIElement m_expanderAddIn;
public Window1()
{
InitializeComponent();
m_stackPanel = new StackPanel { Orientation = Orientation.Vertical };
m_stackPanel.Background = Brushes.Red;
m_expander = new Expander
{
ExpandDirection = ExpandDirection.Right,
Background=Brushes.Blue,
IsExpanded=true,
};
m_expander.Expanded += CheckStuff;
m_expander.Collapsed += CheckStuff;
Rectangle r = new Rectangle {Fill = Brushes.LightGray, Height = 300, Width = 300};
m_expander.Content = r;
m_expanderAddIn = FrameworkElementAdapters.ContractToViewAdapter(FrameworkElementAdapters.ViewToContractAdapter(m_expander));
m_stackPanel.Children.Add(m_expanderAddIn);
Content = m_stackPanel;
}
private void CheckStuff(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Expander: " + m_expander.DesiredSize);
Debug.WriteLine("Add in: " + m_expanderAddIn.DesiredSize);
Debug.WriteLine("Stack Panel: " + m_stackPanel.DesiredSize);
}
}
As you expand and collapse the Expander you would expect the height of the StackPanel to change but it doesn't. Any ideas would be useful, thanks.
That's really weird and I have no idea why it behaves like that. This is probably just a small example reproducing your problem so maybe this doesn't help you much but I got your example working with 3 changes.
Wrap the Expander in a "dummy" StackPanel and use that as the root element for m_expanderAddIn instead. This took care of the Height problem for the Expander.
Change the type of m_expanderAddIn from UIElement to FrameworkElement
Bind the Height of m_expanderAddIn to ActualHeight of m_expander
Code
public partial class Window1 : Window
{
private StackPanel m_stackPanel;
private Expander m_expander;
private FrameworkElement m_expanderAddIn;
public Window1()
{
InitializeComponent();
m_stackPanel = new StackPanel { Orientation = Orientation.Vertical };
m_stackPanel.Background = Brushes.Red;
m_expander = new Expander
{
ExpandDirection = ExpandDirection.Right,
Background=Brushes.Blue,
IsExpanded=true,
};
m_expander.Expanded += CheckStuff;
m_expander.Collapsed += CheckStuff;
Rectangle r = new Rectangle {Fill = Brushes.LightGray, Height = 300, Width = 300};
m_expander.Content = r;
StackPanel stackPanel = new StackPanel();
stackPanel.Children.Add(m_expander);
m_expanderAddIn = FrameworkElementAdapters.ContractToViewAdapter(FrameworkElementAdapters.ViewToContractAdapter(stackPanel));
Binding binding = new Binding("ActualHeight");
binding.Source = m_expander;
m_expanderAddIn.SetBinding(FrameworkElement.HeightProperty, binding);
m_stackPanel.Children.Add(m_expanderAddIn);
Content = m_stackPanel;
}
private void CheckStuff(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Expander: " + m_expander.DesiredSize);
Debug.WriteLine("Add in: " + m_expanderAddIn.DesiredSize);
Debug.WriteLine("Stack Panel: " + m_stackPanel.DesiredSize);
}
}