我试图用画布中的MVVM表示加权图 因此我将图形顶点和边缘表示为可观察的集合并将它们放入画布ItemsControl中。但我找不到任何合理的方法来定位代表重心的文本(图形边缘)
我的画布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>
答案 0 :(得分:1)
添加到您的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
运行时{1}}或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();
}
}