Reputation: 117
derived from the solution of my original problem here
i have now the following xaml:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="450" SizeToContent="WidthAndHeight">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<TabControl Grid.Column="0" MinWidth="200" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<Expander Grid.Column="1" Grid.Row="0" ExpandDirection="Right">
<StackPanel x:Name="cont">
<Label>testtesttesttesttest</Label>
<Label>testtesttesttesttest</Label>
<Label>testtesttesttesttest</Label>
<Label>testtesttesttesttest</Label>
<Label>testtesttesttesttest</Label>
<Label>testtesttesttesttest</Label>
<Label>testtesttesttesttest</Label>
<Label>testtesttesttesttest</Label>
</StackPanel>
</Expander>
</Grid>
</Window>
i want to extend the window width everytime i expand the expander control to the right. when i run the above quoted xaml and expand the expander control after the build, everything works like expected, but as soon as i manually resize the window, the content of the expander control will expand into the existing area to the left.
how can i change this behaviour, so that the window will extend its width to the right side and the content will end up in that new area?
Upvotes: 2
Views: 2082
Reputation: 41393
This isn't something that is built into WPF, so you'd have to write some custom code to handle it. The SizeToContent works until the end-user resizes the window, then the Window size is fixed.
You can use something like this to accomplish what you want:
public partial class MainWindow {
public MainWindow() {
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e) {
base.OnSourceInitialized(e);
IntPtr handle = new WindowInteropHelper(this).Handle;
HwndSource.FromHwnd(handle).AddHook(new HwndSourceHook(this.WindowProc));
}
private const int WM_SIZING = 0x0214;
private const int WM_EXITSIZEMOVE = 0x0232;
private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
switch (msg) {
case WM_SIZING:
this.firstColumn.ClearValue(ColumnDefinition.MinWidthProperty);
break;
case WM_EXITSIZEMOVE:
this.firstColumn.MinWidth = this.firstColumn.ActualWidth;
this.SizeToContent = System.Windows.SizeToContent.WidthAndHeight;
break;
}
return IntPtr.Zero;
}
}
Then you'd need to give your first ColumnDefinition the name "firstColumn", like so:
<ColumnDefinition x:Name="firstColumn" Width="*" />
So effectively, it uses SizeToContent like you have. If you resize the window, then it ensures the first column's minimum size keeps the size fixed and toggles the SizeToContent back on.
EDIT:
Noticed you used the VB.NET tag, so here is the VB.NET version:
Public Partial Class MainWindow
Public Sub New()
InitializeComponent()
End Sub
Protected Overrides Sub OnSourceInitialized(e As EventArgs)
MyBase.OnSourceInitialized(e)
Dim handle As IntPtr = New WindowInteropHelper(Me).Handle
HwndSource.FromHwnd(handle).AddHook(New HwndSourceHook(AddressOf Me.WindowProc))
End Sub
Private Const WM_SIZING As Integer = &H214
Private Const WM_EXITSIZEMOVE As Integer = &H232
Private Function WindowProc(hwnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr, ByRef handled As Boolean) As IntPtr
Select Case msg
Case WM_SIZING
Me.firstColumn.ClearValue(ColumnDefinition.MinWidthProperty)
Exit Select
Case WM_EXITSIZEMOVE
Me.firstColumn.MinWidth = Me.firstColumn.ActualWidth
Me.SizeToContent = System.Windows.SizeToContent.WidthAndHeight
Exit Select
End Select
Return IntPtr.Zero
End Function
End Class
Upvotes: 2