【问题标题】:WPF Position TextBlock/Label on the Line centerWPF 将文本块/标签放在行中心
【发布时间】:2016-10-21 16:53:11
【问题描述】:

我试图用画布内的 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>

What i want to get

【问题讨论】:

    标签: c# wpf xaml canvas binding


    【解决方案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.LeftCanvas.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>
    

    第二种方法

    或者,不要将MarginLeftTop 属性添加到EdgeItem,而是使用值转换器生成边距Thickness。我对在EdgeItem 上拥有这些属性并不感到疯狂,但另一方面,如果你碰巧改变V1V2{Binding} 上的值转换器是提高PropertyChanged 的问题在运行时。解决方案是使其成为多值转换器,并使用多绑定分别绑定 V1V2。我只是懒得写那个 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();
        }
    }
    

    【讨论】:

    • 只是好奇:为什么要从 MarkupExtension 派生 EdgeItemMargin?
    • @HenrikHansen 习惯。可以通过这种方式为它们指定命名和类型(但不是绑定)参数,尽管在这种情况下不需要这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-17
    • 2011-07-15
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    相关资源
    最近更新 更多