一张图片胜过千言万语 - 所以这里是现有的反对理想的:
这是我尝试过的成功:
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);
}
答案 0 :(得分:0)
在下面的解决方案中,我假设您的Canvas
的高度和宽度可以在运行时更改,并且您的TextBlock
也可以具有动态变化的高度和宽度。这种方法看起来很复杂,但并非如此。当然,在XAML中执行此操作会更加可读:
TextBlock
添加到画布。Line
添加到画布。MultiBinding
计算Canvas.Left
的{{1}}属性。如果TextBlock
或Canvas
的宽度发生变化,则此绑定将重新评估,TextBlock
将提供新值。 IMultiValueConverter
的{{1}}值应为:Canvas.Left
- TextBlock
。Canvas.ActualWidth/2
。TextBlock.ActualWidth/2
计算Line
的{{1}}属性。假设您要将线条绘制到MultiBinding
的下边缘。要计算:Line.Y2
- Line
。如果更改和Canvas
将提供新值,绑定将重新评估。Canvas.ActualHeight
在TextBlock.ActualHeight
上设置IMultiValueConverter
属性。在此示例中,Binding
位于Canvas.Top
的正下方,因此我们只能绑定到Line
。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
的新值。
希望这有帮助!