WPF位置TextBlock/Label在行中心
本文关键字:Label 位置 TextBlock WPF | 更新日期: 2023-09-27 18:14:09
我试图在画布内用MVVM表示加权图所以我将图形的顶点和边表示为可观察集合,并将它们放入画布ItemsControl。但是我找不到任何合理的方法来定位表示线(图形边缘)中心的权重的文本
my canvas xaml:
<Canvas Background="Linen" ClipToBounds="True"
Grid.Row="0" Grid.Column="0">
<ItemsControl ItemsSource="{Binding EdgeItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line Stroke="Black" StrokeThickness="4"
X1="{Binding V1.X}" Y1="{Binding V1.Y}"
X2="{Binding V2.X}" Y2="{Binding V2.Y}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
我想要得到什么
添加到您的EdgeItem
类(或您的EdgeItems
集合中的任何内容)。
// When V1 or V2 changes, raise PropertyChanged("Margin")
public Thickness Margin => new Thickness(Left, Top, 0, 0);
public double Left => Math.Min(V1.X, V2.X);
public double Top => Math.Min(V1.Y, V2.Y);
我假设EdgeItem
具有Weight
属性-如果没有,Weight
是您想要在行中心显示的任何属性的替身。我本以为Canvas.Left
和Canvas.Top
会起作用,但对我来说,它们在这种情况下不起作用。
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Line
Stroke="Black"
StrokeThickness="4"
X1="{Binding V1.X}"
Y1="{Binding V1.Y}"
X2="{Binding V2.X}"
Y2="{Binding V2.Y}"
/>
<Label
Background="#ccffffff"
Content="{Binding Weight}"
Margin="{Binding Margin}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<标题> 第二个方法或者,不要将Margin
、Left
和Top
属性添加到EdgeItem
,而是使用值转换器生成边距Thickness
。我对EdgeItem
上的这些属性并不疯狂,但另一方面,{Binding}
上的值转换器是提高PropertyChanged
的问题,如果你碰巧在运行时改变V1
或V2
。解决方案是使其成为多值转换器,并使用多绑定分别绑定V1
和V2
。我只是懒得写XAML。
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Line
Stroke="Black"
StrokeThickness="4"
X1="{Binding V1.X}"
Y1="{Binding V1.Y}"
X2="{Binding V2.X}"
Y2="{Binding V2.Y}"
/>
<Label
Background="#ccffffff"
Content="{Binding Weight}"
Margin="{Binding Converter={local:EdgeItemMargin}}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
转换器:
public class EdgeItemMargin : MarkupExtension, IValueConverter
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
public object Convert(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
var edge = (EdgeItem)value;
return new Thickness(
Math.Min(edge.V1.X, edge.V2.X),
Math.Min(edge.V1.Y, edge.V2.Y),
0, 0);
}
public object ConvertBack(
object value,
Type targetType,
object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
}
标题>