Try to create the viewport for your scrollbar manually and adjust the Width Request from viewport when the SizeRequested Event from child is sent.
For your minimal example it should look like this:
using System;
using Gtk;
namespace ExpanderIssue
{
class MainClass
{
static bool useExpander = true;
private static Widget createScrolledWindow(Widget child)
{
ScrolledWindow scrolledWindow = new ScrolledWindow();
scrolledWindow.SetPolicy(PolicyType.Never, PolicyType.Automatic);
scrolledWindow.Add(doWorkaround(child));
return scrolledWindow;
}
private static Viewport doWorkaround(Widget child)
{
Viewport viewport = new Viewport();
viewport.Add(child);
child.SizeRequested += (o, args) =>
{
viewport.WidthRequest = viewport.Child.Requisition.Width;
};
return viewport;
}
private static Widget createSingleExpaner(int index)
{
Button button = new Button(String.Format("ExampleButton {0}", index));
button.WidthRequest = 800;
if(useExpander) {
Expander expander = new Expander(String.Format("Expander {0}", index));
expander.Add(button);
return expander;
} else {
return button;
}
}
public static void Main(string[] args)
{
Application.Init();
createMainWindow();
Application.Run();
}
private static Window createMainWindow()
{
VBox vbox = new VBox();
vbox.Spacing = 4;
for(int i=0; i<32; ++i)
vbox.PackStart(createSingleExpaner(i), false, false, 0);
Window mainWindow = new Window("Expander Width Request issue");
mainWindow.SetDefaultSize(240, 160);
mainWindow.Add(createScrolledWindow(vbox));
mainWindow.ShowAll();
mainWindow.Destroyed += (sender, e) => Application.Quit();
return mainWindow;
}
}
}