如何在运行时绘制从文本框中间退出的行?

时间:2011-12-18 14:51:54

标签: wpf

一张图片胜过千言万语 - 所以这里是现有的反对理想的:

enter image description here

这是我尝试过的成功:

 public MainWindow()
    {
        InitializeComponent();
        TextBlock txt = new TextBlock();
        txt.Text = "asdsahd sakh uj";
        txt.Background = Brushes.LightBlue;
        Canvas.SetLeft(txt, 100);
        container.Children.Add(txt);


        Line line = new Line();
        line.SetBinding(Line.X1Property, new Binding("Canvas.Left") {ElementName = "txt"});
        line.X2 = line.X1;
        line.Y1 = 0;
        line.Y2 = 100;
        line.StrokeThickness = 2;
        container.Children.Add(line);
    }

1 个答案:

答案 0 :(得分:0)

在下面的解决方案中,我假设您的Canvas的高度和宽度可以在运行时更改,并且您的TextBlock也可以具有动态变化的高度和宽度。这种方法看起来很复杂,但并非如此。当然,在XAML中执行此操作会更加可读:

  1. 创建TextBlock添加到画布。
  2. 创建Line添加到画布。
  3. 使用MultiBinding计算Canvas.Left的{​​{1}}属性。如果TextBlockCanvas的宽度发生变化,则此绑定将重新评估,TextBlock将提供新值。 IMultiValueConverter的{​​{1}}值应为:Canvas.Left - TextBlock
  4. 与步骤3相同,但这次适用于Canvas.ActualWidth/2
  5. 使用TextBlock.ActualWidth/2计算Line的{​​{1}}属性。假设您要将线条绘制到MultiBinding的下边缘。要计算:Line.Y2 - Line。如果更改和Canvas将提供新值,绑定将重新评估。
  6. 使用Canvas.ActualHeightTextBlock.ActualHeight上设置IMultiValueConverter属性。在此示例中,Binding位于Canvas.Top的正下方,因此我们只能绑定到Line
  7. TextBlock和线条创建

    Line

    MultiConverter计算行的长度

    TextBlock

    MultiConverter在画布上水平居中元素

    TextBlock.ActualHeight

    修改

    为了使上述代码更加清晰 - 它实际上只是以下XAML的1对1翻译(使用上面的 public MainWindow() { InitializeComponent(); // Create TextBlock and Line var textBlock = new TextBlock {Text = "123456"}; var line = new Line { StrokeThickness = 2, Stroke = new SolidColorBrush { Color = Colors.Black }, Y1 = 0 }; myCanvas.Children.Add(textBlock); myCanvas.Children.Add(line); // Setup bindings InitializeTextBlockCanvasLeftBinding(myCanvas, textBlock); InitializeLineCanvasLeftBinding(myCanvas, line); InitializeLineY2Binding(myCanvas, textBlock, line); InitializeLineCanvasTopBinding(myCanvas, textBlock, line); } private void InitializeLineCanvasTopBinding(Canvas canvas, TextBlock textBlock, Line line) { var textBlockActualHeightBinding = new Binding { Source = textBlock, Path = new PropertyPath("ActualHeight"), }; BindingOperations.SetBinding(line, Canvas.TopProperty, textBlockActualHeightBinding); } private void InitializeLineY2Binding(Canvas canvas, TextBlock textBlock, Line line) { var canvasActualHeightBinding = new Binding { Source = myCanvas, Path = new PropertyPath("ActualHeight"), }; var textBlockActualHeightBinding = new Binding { Source = textBlock, Path = new PropertyPath("ActualHeight"), }; var lineY2MultiBinding = new MultiBinding { Converter = new LineY1MultiConverter() }; lineY2MultiBinding.Bindings.Add(textBlockActualHeightBinding); lineY2MultiBinding.Bindings.Add(canvasActualHeightBinding); BindingOperations.SetBinding(line, Line.Y2Property, lineY2MultiBinding); } private void InitializeLineCanvasLeftBinding(Canvas canvas, Line line) { var lineActualWidthBinding = new Binding { Source = line, Path = new PropertyPath("ActualWidth"), }; var canvasActualWidthBinding = new Binding { Source = myCanvas, Path = new PropertyPath("ActualWidth"), }; var lineLeftMultiBinding = new MultiBinding { Converter = new CanvasLeftCenterMultiConverter() }; lineLeftMultiBinding.Bindings.Add(lineActualWidthBinding); lineLeftMultiBinding.Bindings.Add(canvasActualWidthBinding); BindingOperations.SetBinding(line, Canvas.LeftProperty, lineLeftMultiBinding); } private void InitializeTextBlockCanvasLeftBinding(Canvas canvas, TextBlock textBlock) { var textBlockActualWidthBinding = new Binding { Source = textBlock, Path = new PropertyPath("ActualWidth"), }; var canvasActualWidthBinding = new Binding { Source = myCanvas, Path = new PropertyPath("ActualWidth"), }; var textBlockLeftMultiBinding = new MultiBinding { Converter = new CanvasLeftCenterMultiConverter() }; textBlockLeftMultiBinding.Bindings.Add(textBlockActualWidthBinding); textBlockLeftMultiBinding.Bindings.Add(canvasActualWidthBinding); BindingOperations.SetBinding(textBlock, Canvas.LeftProperty, textBlockLeftMultiBinding); } ):

    public class LineY1MultiConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values != null && values.Length == 2 && values[0] is double && values[1] is double)
            {
                var canvasHeight = (double)values[1];
                var textBlockHeight = (double) values[0];
                return canvasHeight - textBlockHeight;
            }
    
            return DependencyProperty.UnsetValue;
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    如您所见 - 如果画布大小更改,文本大小更改或线条粗细更改,则绑定会确保计算public class CanvasLeftCenterMultiConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { if (values != null && values.Length == 2 && values[0] is double && values[1] is double) { var canvasMiddle = (double)values[1]/2; var elementHalf = (double) values[0]/2; return canvasMiddle - elementHalf; } return DependencyProperty.UnsetValue; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } MultiValueConverters的新值。

    希望这有帮助!