我有一个使用mvvm方法的wpf应用程序。主窗口包含一个选项卡控件。
选项卡控件中的每个项目都有自己的视图模型,每个选项卡项目都包含一个包装面板。我创建了一个附加属性,允许我绑定到面板的ActualHeight和ActualWidth属性。 (我没有使用高度/宽度属性,因为我需要面板来填充可用空间。)
调整窗口大小时,活动选项卡上的面板会调整大小,但其他选项卡上的所有面板都不会更新。观察绑定只会通知一个更改。
这是使用WPF的预期行为吗?如果没有我的方法有什么问题,或者如果有的话有办法强制所有标签更新?
答案 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
}