为何措施不尊重MinWidth
和MinHeight
。
FrameworkElement fe = new FrameworkElement() { MinWidth = 100, MinHeight = 100 };
fe.Measure(new Size(50,50));
// Why: fe.DesireSize == {50; 50} and not {100; 100}?.
这背后的理由是什么? MeasureOverride
是否应始终返回最大可用尺寸?使用无限大小进行测量会导致{100; 100}
。
虽然我问可能与定义UIElement
方法的Measure
有关。我猜FrameworkElement
无法通过MinWidth
和MinHeight
来削弱措施后期条件。
编辑:再次看之后,对Measure的调用似乎已经反映了子项上(最小/最大)宽度和高度的约束。父级正在限制其子级遵守指定的/最小/最大值。
在我的情况下:fe.Measure(new Size(fe.MinWidth, fe.MinHeight));
本来是正确的电话。
我的用例的一些背景知识。我需要一个用于物品控制的面板。物品最多获得“剩余空间”的百分比,但我想尊重物品的最小宽度或设定宽度
例如:
首先取2个文本框,其中一个内容超过100长度,第二个文本框的MinWidth为100.当MyPanel小于200像素时,第一个文本框应为第二个文本框留下100个像素。如何确定第一个文本框的可用大小?当说面板的宽度为150时。第一个文本框不应该取75而是50.它几乎(如果第二个文本框文本为空)就像一个网格,其中第一个列宽为*,第二个列宽为auto。但现在让网格决定第二个列宽是自动的,因为文本框具有非零的最小宽度(或设置宽度)。如果第二个文本框有很多文本,网格的行为应该像第二个列宽也是*。
到目前为止,我有:
public class MyPanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
double desiredWidth = 0;
foreach (UIElement child in InternalChildren)
{
child.Measure(availableSize);
desiredWidth += child.DesiredSize.Width;
}
Size result = new Size();
int i = InternalChildren.Count;
foreach (UIElement child in InternalChildren)
{
double availableWidthMinimum = Math.Max(0, (availableSize.Width - result.Width) / i);
desiredWidth -= child.DesiredSize.Width;
double availableWidthMaximum = Math.Max(0, (availableSize.Width - result.Width - desiredWidth));
double availableWidth = Math.Max(availableWidthMinimum, availableWidthMaximum);
child.Measure(new Size(availableWidth, availableSize.Height));
result.Width += child.DesiredSize.Width;
result.Height = Math.Max(result.Height, child.DesiredSize.Height);
i--;
}
return result;
}
protected override Size ArrangeOverride(Size arrangeSize)
{
Point start = new Point(0, 0);
foreach (UIElement child in InternalChildren)
{
child.Arrange(new Rect(start, child.DesiredSize));
start.X += child.DesiredSize.Width;
}
return arrangeSize;
}
}
XAML:
<local:MyPanel Margin="100,0,0,0">
<TextBox MinWidth="100" Margin="10">MinWidth=100</TextBox>
<TextBox MinWidth="0" Margin="10">MinWidth=000</TextBox>
<TextBox MinWidth="0" Margin="10">Small</TextBox>
<TextBox MinWidth="0" Margin="10">MinWidth=000</TextBox>
</local:MyPanel>
这种工作方式,但在调整包含面板的窗口大小时,第一个文本框应保持至少100。你会注意到第4个文本框仍然比第二个文本框大一些。 (两者应首先变得与第3个一样小:[Min200][Large][Small][Large]
- &gt; [Min200][Small][Small][Small]
)
答案 0 :(得分:0)
DesiredSize
反映了元素相对于其容器的实际/潜在可见大小。
来自https://msdn.microsoft.com/en-us/library/system.windows.uielement(v=vs.110).aspx:
<强> DesiredSize 强>
获取此元素在布局过程的度量传递期间计算的大小。
由Measure
计算的方式解释为here:
public void Measure(Size availableSize)
<强>参数强>
availableSize
输入:System.Windows.Size
父元素可以分配子元素的可用空间。子元素可以请求比可用空间更大的空间;如果在当前元素的内容模型中可以滚动,则可以提供所提供的大小。
(强调我的。)
我已经汇总了一些证明这一点的例子:
元素为按钮内容
MainWindow.xaml
<Window x:Class="DesiredSizeTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="300">
<Grid>
<Button Click="Button_Click" Width="50" Height="50" Padding="0" BorderThickness="0">
<Button.Content>
<Label x:Name="lbl" MinWidth="100" MinHeight="100" />
</Button.Content>
</Button>
</Grid>
</Window>
在MainWindow.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine(lbl.DesiredSize);
Debug.WriteLine(lbl.ActualWidth);
Debug.WriteLine(lbl.ActualHeight);
}
点击输出
50,50
100
100
此示例类似于将new Size(50,50)
传递给Measure
。
切换到StackPanel
<Grid>
<StackPanel Width="50" Height="50" Orientation="Vertical">
<Label x:Name="lbl" MinWidth="100" MinHeight="100" />
</StackPanel>
<Button Click="Button_Click" Width="50" Height="50" Padding="0" BorderThickness="0" VerticalAlignment="Bottom" />
</Grid>
点击输出
50,100
100
100
切换StackPanel方向
<Grid>
<StackPanel Width="50" Height="50" Orientation="Horizontal">
<Label x:Name="lbl" MinWidth="100" MinHeight="100" />
</StackPanel>
<Button Click="Button_Click" Width="50" Height="50" Padding="0" BorderThickness="0" VerticalAlignment="Bottom" />
</Grid>
点击输出
100,50
100
100
使用ScrollViewer
<Grid>
<ScrollViewer Width="50" Height="50" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Label x:Name="lbl" MinWidth="100" MinHeight="100" />
</ScrollViewer>
<Button Click="Button_Click" Width="50" Height="50" Padding="0" BorderThickness="0" VerticalAlignment="Bottom" />
</Grid>
点击输出
100,100
100
100
<强>更新强>
关于下面评论中描述的场景,这是非常动态的,但您可以使用转换器来实现:
<Grid x:Name="grd" Width="250">
<Grid.ColumnDefinitions>
<ColumnDefinition>
<ColumnDefinition.Width>
<MultiBinding Converter="{StaticResource glc}" ConverterParameter="1">
<Binding Path="ActualWidth" ElementName="grd" />
<Binding Path="MinWidth" ElementName="tb" />
</MultiBinding>
</ColumnDefinition.Width>
</ColumnDefinition>
<ColumnDefinition>
<ColumnDefinition.Width>
<MultiBinding Converter="{StaticResource glc}" ConverterParameter="0">
<Binding Path="ActualWidth" ElementName="grd" />
<Binding Path="MinWidth" ElementName="tb" />
</MultiBinding>
</ColumnDefinition.Width>
</ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="............................................................................." />
<TextBox x:Name="tb" Grid.Column="1" MinWidth="100" Text="............................................................................." />
</Grid>
StaticResource
“glc”指的是以下转换器:
public class GridLengthConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Count() == 2 && values[0] is double && values[1] is double)
{
double gridActualWidth = (double)values[0];
double tbMinWidth = (double)values[1];
if (gridActualWidth >= tbMinWidth * 2)
{
return new GridLength(1, GridUnitType.Star);
}
else
{
return parameter.ToString() == "0" ? new GridLength(tbMinWidth) : new GridLength(gridActualWidth - tbMinWidth);
}
}
return new GridLength(1, GridUnitType.Star);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
在运行时,如果需要使用它们,您可以访问所有ActualWidth
/ ActualHeight
属性值。