Reputation: 43
Hi I want my button in my C# WPF program to autosize depending on content. This is what I already mentioned.
But now I want to know what width the button actually got.
I tried button.ActualWidth
and button.width
. The first returned "0" and the second returned "NaN".
My XAML for the button
<Button x:Name="button1" Content="Button" HorizontalAlignment="Left" Margin="61,41,433,0" VerticalAlignment="Top" IsEnabled="False" Click="button1_Click"/>
New content of my button:
button1.Content = "new content xayxax ";
nWidth = button.ActualWidth;
MessageBox.Show(nWidth.ToString());
This Messagebox displays "0"
Upvotes: 0
Views: 2701
Reputation: 169280
As suggested by @Sinatr (+1) you need to measure the Button
after you have set its Content
property - or wait until WPF measures it for you - but make sure that you use an large enough available space when you measure it:
button1.Content = "new content xayxax ";
var size = new Size(double.PositiveInfinity, double.PositiveInfinity);
button1.Measure(size);
button1.Arrange(new Rect(button1.DesiredSize));
MessageBox.Show(button1.ActualWidth.ToString());
This should display "110,703" which is the actual size of the Button
after its Content
has been updated.
Upvotes: 2
Reputation: 21999
ActualWidth
should never be NaN
(it starts from 0
before measure and arrange) , but Width
can. Width == NaN
means control width wasn't locally set and the control actual size will depends on layout.
Use ActualWidth
to get width of control after measure and arrange:
var button = new Button();
button.Content = "123";
button.HorizontalAlignment = HorizontalAlignment.Left;
button.Measure(new Size(100, 100));
button.Arrange(new Rect(0, 0, 100, 100));
MessageBox.Show(button.ActualWidth.ToString()); // Output: 23,41
You don't event need a window (the way how WPF engine works), but you must to call Measure
and Arrange
.
Changing Content
will not refresh the control, that would occurs some time later, you can invoke the call like this to get it:
void button_Click(object sender, RoutedEventArgs e)
{
button.Content = "123";
//MessageBox.Show(button.ActualWidth.ToString()); // output: 0
Dispatcher.Invoke(() => MessageBox.Show(button.ActualWidth.ToString()), DispatcherPriority.Render); // correct output
}
First message box will still display old size, new size become available only measure/arrange. Invoke with DispatcherPriority.Render
will ensure what render occurs (it will do measure/arrange), returning correct new size.
If you can't wait with invoke, then just call Measure
and Arrange
yourself (passing parent container available size, or just invoking it on the root element of visual tree).
Upvotes: 2