Ограничения размера окна по содержимому
Я хочу чтобы окно уважало MinWidth
/MinHeight
а также MaxWidth
/MaxHeight
Спецификации управления контентом внутри.
Некоторые предложили использовать SizeToContent
, но это только помогает установить начальный размер окна, а не ограничения.
Другие предложили переопределить MeasureOverride
и установка минимальной / максимальной высоты и ширины окна там, но это кажется несколько нечистым, учитывая, что такая тривиальная проблема, безусловно, должна иметь чисто декларативное решение.
Просто упомянуть другое решение, которое кажется разумным, но не работает (и было упомянуто ранее в ответе, который был удален): обязательный MinWidth
окна в MinWidth
управления не учитывает оформление окон.
3 ответа
Если начальный размер окна установлен так, что фактический размер содержимого не приводится в соответствие MinWidth/MinHeight и MaxWidth/MaxHeight содержимого на начальном этапе макета (например, с помощью Window.SizeToContent="WidthAndHeight"), тогда следующие уравнения верны:
Window.ActualSize - Content.ActualSize =
Window.MinSize - Content.MinSize = Window.MaxSize - Content.MaxSize.
На основании этих уравнений вы можете получить следующий код:
public MainWindow()
{
InitializeComponent();
this.SizeChanged += OnWindowSizeChanged;
}
private static void OnWindowSizeChanged(object sender, SizeChangedEventArgs e)
{
var window = (Window)sender;
var content = (FrameworkElement)window.Content;
window.MinWidth = window.ActualWidth - content.ActualWidth + content.MinWidth;
window.MaxWidth = window.ActualWidth - content.ActualWidth + content.MaxWidth;
window.MinHeight = window.ActualHeight - content.ActualHeight + content.MinHeight;
window.MaxHeight = window.ActualHeight - content.ActualHeight + content.MaxHeight;
window.SizeChanged -= OnWindowSizeChanged;
}
Я не знаю, как добиться этого эффективно, используя чистый декларативный подход, так как код должен быть запущен только один раз после начального этапа компоновки.
Некоторые предложили использовать
SizeToContent
, но это только помогает установить начальный размер окна, а не ограничения.
Я работал над этим, установив MinWidth
а также MinHeight
Свойства сразу после инициализации окна:
MainWindow.xaml
<Window ... SizeToContent="WidthAndHeight">
...
</Window>
MainWindow.xaml.cs
public MainWindow()
{
InitializeComponent();
SourceInitialized += (s, e) =>
{
MinWidth = ActualWidth;
MinHeight = ActualHeight;
};
}
Используйте расширение разметки Binding. Привязка - это способ выражения wpf, когда это свойство (источник) изменяется, обновляет другое свойство (цель). В этом случае свойство MinWidth Grid является источником, а свойство MinWidth вашего окна является целью.
<Window x:Class="MinMaxValuesOnWindows.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="800"
MinWidth="{Binding ElementName=gridy, Path=MinWidth}"
MinHeight="{Binding ElementName=gridy, Path=MinHeight}"
MaxWidth="{Binding ElementName=gridy, Path=MaxWidth}"
MaxHeight="{Binding ElementName=gridy, Path=MaxHeight}">
<Grid Name="gridy" MinHeight="80" MinWidth="80" MaxHeight="300" MaxWidth="300"/>
</Window>
Как вы упомянули в теме, это не полностью работает, но вы можете использовать конвертер для привязки, чтобы добавить высоту и ширину оконной рамы перед обновлением цели привязки (может потребоваться PInvoke). Поскольку я сомневаюсь, что толщина рамки окна в вашем приложении динамически изменяется, это, вероятно, может быть просто постоянным значением (не обязательно истинным, если пользователь меняет темы).