Ограничения размера окна по содержимому

Я хочу, чтобы окно в отношении MinWidth/MinHeight и MaxWidth/MaxHeight спецификации content control внутри.

некоторые предложили использовать 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;
    };
}

используйте расширение разметки привязки. Привязка-это способ wpf сказать, когда это свойство (источник) изменяет обновление некоторого другого свойства (цели). В этом случае свойство MinWidth сетки является источником, а свойство 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). С Я сомневаюсь, что толщина оконной рамы динамически меняется в вашем приложении, это может быть просто постоянное значение (не обязательно верно, если пользователь меняет темы).