调整窗口和绑定的大小不符合预期

时间:2011-11-14 14:14:31

标签: wpf mvvm resize

我有一个使用mvvm方法的wpf应用程序。主窗口包含一个选项卡控件。

选项卡控件中的每个项目都有自己的视图模型,每个选项卡项目都包含一个包装面板。我创建了一个附加属性,允许我绑定到面板的ActualHeight和ActualWidth属性。 (我没有使用高度/宽度属性,因为我需要面板来填充可用空间。)

调整窗口大小时,活动选项卡上的面板会调整大小,但其他选项卡上的所有面板都不会更新。观察绑定只会通知一个更改。

这是使用WPF的预期行为吗?如果没有我的方法有什么问题,或者如果有的话有办法强制所有标签更新?

1 个答案:

答案 0 :(得分:1)

每个TabItem听起来都是分开绘制的。通常WPF会卸载不可见的TabItem,因此在Window的大小更改时,只存在一个WrapPanel。当您通过切换选项卡重新加载TabItem时,如果未绑定某些内容(例如ActualHeight),则它将重新加载到其在XAML中定义的原始值

通常我更喜欢将我的尺寸存储为百分比,然后使用转换器将百分比转换为实际尺寸

我通常使用的转换器如下。我刚开始使用WPF时创建了这个,我当时并不知道有MultiConverters。我敢肯定它可以重写为多转换器,但我还没有完成它。

要使用它,请将转换器添加到资源

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

根据Converter

设置绑定
<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
}