Изменение размера окна и привязок не работает должным образом - PullRequest
1 голос
/ 14 ноября 2011

У меня есть приложение wpf, использующее подход mvvm. Главное окно содержит вкладку управления.

Каждый элемент в элементе управления вкладками имеет свою собственную модель представления, а каждый элемент вкладки содержит панель переноса. Я создал прикрепленное свойство, которое позволяет мне привязывать свойства ActualHeight и ActualWidth панели. (Я не использовал свойства высоты / ширины, так как мне нужна панель для заполнения доступного пространства.)

При изменении размера окна размер активной вкладки изменяется, однако все панели других вкладок не обновляются. При просмотре привязок уведомляется только одно изменение.

Это ожидаемое поведение при использовании WPF? Если нет, что не так с моим подходом, или, если да, есть ли способ заставить все вкладки обновиться?

1 Ответ

1 голос
/ 14 ноября 2011

Каждый TabItem звучит так, как будто он рисуется отдельно. Обычно WPF выгружает TabItems, которые не видны, поэтому во время изменения размера окна существует только одна WrapPanel, которая существует. Когда вы перезагружаете TabItem путем переключения вкладок, если что-то не связано (например, ActualHeight), тогда он перезагрузится к своим исходным значениям, определенным в вашем XAML

Обычно я предпочитаю хранить свои размеры в процентах, а затем использовать конвертер для преобразования процента в фактический размер

Конвертер, который я обычно использую, находится ниже. Я создал это, когда впервые начал работать с WPF, и я не знал, что в то время существовали мультиконвертеры. Я уверен, что он может быть переписан как мультиконвертер, однако я еще не удосужился сделать это.

Чтобы использовать его, добавьте конвертер в свои ресурсы

<local:PercentOfParentConverter x:Key="PanelHeightConverter" />
<local:PercentOfParentConverter x:Key="PanelWidthConverter" />

Установите привязки на основе конвертера

<Setter Property="Height" Value="{Binding Path=PanelHeight, 
            Converter={StaticResource PanelHeightConverter}}" />
<Setter Property="Width" Value="{Binding Path=PanelWidth, 
            Converter={StaticResource PanelWidthConverter}}" />

А в Code-Behind обязательно подключитесь к событию SizeChanged, чтобы обновить ParentSize конвертера при каждом изменении размера

// If workarea size changes, reposition/resize panels within it to keep the same layout
private void PanelSizeChanged(object sender, SizeChangedEventArgs e)
{
    Panel c = sender as Panel;
    if (c != null)
    {
        // Set the parent's height/width on the converter
        PercentOfParentConverter sizeConverter = (PercentOfParentConverter)c.FindResource("PanelHeightConverter");
        if (sizeConverter != null) sizeConverter.ParentSize = c.ActualHeight;

        sizeConverter = (PercentOfParentConverter)c.FindResource("PanelWidthConverter");
        if (sizeConverter != null) sizeConverter.ParentSize = c.ActualWidth;

        foreach (UIElement child in c.Children)
        {
            RebindPanelSizeAndPosition(child);
        }
    }
}

// Refreshes the Panel.Height/Width bindings of the UIElement passed to it
private void RebindPanelSizeAndPosition(UIElement element)
{
    BindingOperations.GetBindingExpressionBase(element, Panel.HeightProperty).UpdateTarget();
    BindingOperations.GetBindingExpressionBase(element, Panel.WidthProperty).UpdateTarget();
}

Фактический код конвертера выглядит следующим образом:

// Converts a percent to a double value based on the parent size set
public class PercentOfParentConverter : IValueConverter
{
    public double ParentSize { get; set; }

    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var percent = (double) value;
        return percent*ParentSize;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (ParentSize != 0)
        {
            return (double) value/ParentSize;
        }
        else
        {
            return 0;
        }
    }

    #endregion
}
...