Zoo*_*Way 4 wpf datatemplate attached-properties
我得到了一个ItemsControl使用Canvasas 的项目ItemsPanel,它的项目根据绑定类型呈现为不同的 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>
Run Code Online (Sandbox Code Playgroud)
因此,我基本上将对象添加到PreviewShapes视图模型中,并根据它们渲染到 WPFLine或Ellipses 的类型。这基本上可以工作,但附加的属性Canvas.Left和Canvas.Top会被忽略,即使使用静态值也是如此。
VS 或 ReSharper 还通知我附加属性在当前上下文中无效。
如何Ellipse在不使用附加属性的情况下将 放置在画布上?或者还有什么其他合适的解决方案?
不幸的是没有人愿意发布答案。
首先,克莱门斯链接很有帮助。这些项目将位于 a 内,这就是为什么对 进行设置不起作用的ContentPresenter原因。Canvas.Left/TopEllipsis
解决方案1
通过向项目容器添加样式,可以在那里设置位置的绑定:
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding UpperLeft.X}" />
<Setter Property="Canvas.Top" Value="{Binding UpperLeft.Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
Run Code Online (Sandbox Code Playgroud)
这可行,但DataTemplate放置<Line>会产生绑定警告,因为该视图模型没有属性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>
Run Code Online (Sandbox Code Playgroud)
他们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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
希望有人会发现一种或两种有用的解决方案。
| 归档时间: |
|
| 查看次数: |
1890 次 |
| 最近记录: |