gpt4 book ai didi

wpf - 使附加属性在 DataTemplate 中工作

转载 作者:行者123 更新时间:2023-12-02 00:13:21 24 4
gpt4 key购买 nike

我有一个ItemsControl,它使用Canvas作为ItemsPanel,并且它的项目基本上根据绑定(bind)类型呈现为不同的WPF形状像这样:

<ItemsControl  ItemsSource="{Binding PreviewShapes}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:UiPreviewLineViewModel}">
<Line X1="{Binding Start.X}" Y1="{Binding Start.Y}"
X2="{Binding End.X}" Y2="{Binding End.Y}"
StrokeThickness="0.75" Stroke="{Binding Brush}" x:Name="Line" ToolTip="{Binding Text}">
</Line>
</DataTemplate>
<DataTemplate DataType="{x:Type local:UiPreviewEllipsisViewModel}">
<Ellipse Canvas.Left="{Binding UpperLeft.X" Canvas.Top="{Binding UpperLeft.Y}"
Width="{Binding Width}" Height="{Binding Height}"
StrokeThickness="0.75" Stroke="{Binding Brush}" x:Name="Ellipse" ToolTip="{Binding Text}">
</Ellipse>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="SketchCanvas" ClipToBounds="False">
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>

因此,我基本上将对象添加到 View 模型的 PreviewShapes 中,并根据它们渲染为 WPF LineEllipse 的类型。这基本上可以工作,但附加属性 Canvas.LeftCanvas.Top 会被忽略,即使使用静态值也是如此。

VS 或 ReSharper 还通知我附加属性在当前上下文中无效。

如何在不使用附加属性的情况下将椭圆定位在 Canvas 上?或者还有什么其他合适的解决方案?

最佳答案

不幸的是,没有人愿意发布答案。

首先,克莱门斯链接很有帮助。这些项目将位于 ContentPresenter 内这就是为什么设置Canvas.Left/Top的原因关于Ellipsis不起作用。

解决方案1

通过向项目容器添加样式,可以在那里设置位置的绑定(bind):

<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding UpperLeft.X}" />
<Setter Property="Canvas.Top" Value="{Binding UpperLeft.Y}" />
</Style>
</ItemsControl.ItemContainerStyle>

这有效,但是 DataTemplate放置<Line>将产生绑定(bind)警告,因为该 View 模型没有属性 UpperLeft 。尽管如此,它适用于省略号,并且行按其 X1 放置。 , Y1 , X2Y2值。

解决方案2

如果您想使用更细粒度的控制方法,您可以设置附加的 Canvas属性为 ContentPresenter通过使用自定义行为/附加属性代理它们。我们将其命名为 CanvasPointProxyBehavior,您可以将其用于 Ellipse像这样:

<DataTemplate DataType="{x:Type local:UiPreviewEllipsisViewModel}">
<Ellipse behaviors:CanvasPointProxyBehavior.Point="{Binding UpperLeft}"
Width="{Binding Width}" Height="{Binding Height}"
StrokeThickness="0.75" Stroke="{Binding Brush}" x:Name="Ellipse" ToolTip="{Binding Text}">
</Ellipse>
</DataTemplate>

Line不会需要它。此附加属性的代码可能如下所示:

public class CanvasPointProxyBehavior
{
public static readonly DependencyProperty PointProperty = DependencyProperty.RegisterAttached("Point", typeof(Point), typeof(CanvasPointProxyBehavior), new UIPropertyMetadata(null, PointChangedCallback));

public static void SetPoint(DependencyObject depObj, Point point)
{
depObj.SetValue(PointProperty, point);
}

public static Point GetPoint(DependencyObject depObj)
{
return depObj.GetValue(PointProperty) as Point;
}

private static void PointChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
UIElement uiElement = (dependencyObject as UIElement);
if (uiElement == null) return;
UIElement elementToBePositioned = uiElement;
var visualParent = VisualTreeHelper.GetParent(uiElement);
if (visualParent is ContentPresenter)
{
elementToBePositioned = visualParent as ContentPresenter;
}

var point = e.NewValue as Point;
if (point != null)
{
Canvas.SetLeft(elementToBePositioned, point.X);
Canvas.SetTop(elementToBePositioned, point.Y);
}
}
}
<小时/>

希望有人会发现一种或两种有用的解决方案。

关于wpf - 使附加属性在 DataTemplate 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40329007/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com