I've been trying to pass a UserControl through AppDomain boundaries and noticed a weird behavior with FrameworkElementAdapters.ViewToContractAdapter()
and ContractToViewAdapter()
. After the INativeHandleContract
has been converted back to a FrameworkElement
using FrameworkElementAdapters.ContractToViewAdapters()
, the wrapped UserControl doesn't change its size anymore if one of its children grows.
This behavior can be easily demonstrated using a simple, empty, WPF window:
public partial class MainWindow : Window
{
private ListBox listBox;
private Button myButton;
public MainWindow()
{
InitializeComponent();
listBox = new ListBox();
Content = listBox;
myButton = new Button { Content = "Click me" };
myButton.Click += (sender, args) => myButton.Content = "Lorem ipsum dolor sit amet.";
myButton.SizeChanged += (sender, args) => Debug.WriteLine($"{myButton.DesiredSize}");
//listBox.Items.Add(myButton);
var frameworkElement = FrameworkElementAdapters.ContractToViewAdapter(FrameworkElementAdapters.ViewToContractAdapter(myButton));
listBox.Items.Add(frameworkElement);
}
}
If you click the button, the text changes as expected. the button doesn't resize itself, though, which leaves you with a truncated text. If you comment out the last two lines and just add the button, it will work as expected.
I think its basically the same problem as in this case, but there doesn't seem to be a solution. Does anyone have an idea how to get rid of this?
Thanks in advance!
As mentioned in my comment, additionally wrapping everything in a Grid
seems to do the trick or, at least, allows you to receive a SizeChanged
event which you can then use to resize the resulting FrameworkElement
.
public partial class MainWindow : Window
{
private ListBox listBox;
private Button myButton;
private Grid dummyGrid;
public MainWindow()
{
InitializeComponent();
listBox = new ListBox();
Content = listBox;
myButton = new Button { Content = "Click me" };
myButton.Click += (sender, args) =>
{
myButton.Content = "Lorem ipsum dolor sit amet.";
myButton.FontSize = 24;
};
dummyGrid = new Grid();
dummyGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
dummyGrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
dummyGrid.Children.Add(myButton);
var frameworkElement =
FrameworkElementAdapters.ContractToViewAdapter(
FrameworkElementAdapters.ViewToContractAdapter(dummyGrid));
listBox.Items.Add(frameworkElement);
// Automatically adjust HwndHost's size when the grid changes
dummyGrid.SizeChanged += (sender, args) =>
{
frameworkElement.Width = args.NewSize.Width;
frameworkElement.Height = args.NewSize.Height;
};
}
}
In my case i had to do some magic to get the event to pass through the AppDomain boundaries (e.g. SizeChangedEventArgs
not beeing serializable etc.).