4

UWP has a design problem: ActualHeight/ActualWidth, which store the result of the layout operations, are always a real number. However, because they are updated so frequently, UWP does not notify when they change.

Height/Width do provide change notifications, but may often be NaN, as when the object is set to stretch to fill a parent.

It seems like the answer is: Don't. Subscribe to SizeChanged and directly adjust properties that depend on size, using ActualHeight and ActualWidth.

However, I'm encountering another problem with the latter, where not all child controls redraw correctly, and it seems to be because the SizeChanged event sometimes gets dropped, and so some child controls get stuck with an old size value. This problem gets more noticeable with rapid resizing. A slow small resize causes them to redraw correctly. I'm guessing that for performance, UWP rendering framework tries to reduce the amount of work happening while drawing.

What's the right way to do this? And/or if I continue using SizeChanged, how can I either ensure that the final values are rendered, or that the work done is reduced so that all SizeChanged events are received?

(w/ Win10 16299 SDK)

UPDATE: The misbehavior of SizeChanged was in part due to my misordering of the event handler logic. However, there are sill frames in which objects that should be positioned identically are misaligned. On further inspection, that appears to be a bug in Grid positioning.

Nick Bauer
  • 1,027
  • 8
  • 13

1 Answers1

3

Let's assume you have 2 elements: a TextBox and a ComboBox. You want whenever the textbox's size change, the combobox's size should be changed too. See this.

<TextBox Name="TextBox1"></TextBox>
<ComboBox Width={Binding ElementName=TextBox1 Path=Width}
          Height={Binding ElementName=TextBox1 Path=Height}><ComboBox/>

If you want to bind in cs file. You can do this:

    TextBox TextBox1=new TextBox();
    Binding WidthBinding=new Binding();
    WidthBinding.Source=ViewModelClass;
    WidthBinding.Path=new PropertyPath("WidthPropertyInViewModelClass");
    WidthBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    BindingOperations.SetBinding(TextBox1, TextBox.WidthProperty, WidthBinding);

For more information about binding in code file, see this, and this

Red Wei
  • 854
  • 6
  • 22
  • I appreciate that, though my needs are a bit more complex. I have objects dynamically added in code, and I'm positioning them proportionally via a ValueConverter with a parameter. And when the object is autosized, as I said, Height and Width are NaN regardless of the size of the element. – Nick Bauer Oct 19 '17 at 04:55
  • 1
    @NickBauer `Width` and `Height` will always be `NaN` if you never set them. You may use `ActualWidth` and `ActualHeight` or `RenderSize` - these properties are initialized after `SizeChanged` event. And try to use `x:Bind` - it' faster and has more features. – Jet Chopper Oct 19 '17 at 06:14
  • @NickBauer I updated the answer, I hope I can help you. – Red Wei Oct 19 '17 at 08:57