【问题标题】:CustomControl XAML: ArcSegment.Size binding to control's Actual Width and HeightCustomControl XAML:ArcSegment.Size 绑定到控件的实际宽度和高度
【发布时间】:2020-07-11 12:11:29
【问题描述】:

我的程序员伙伴们!

我已经搜索了 Internet,但找不到解决方案。这可能是因为我是 WPF 的新手。我正在努力实现以下目标:

CustomControl 有一个ArcSegment,其Size 绑定到CustomControl 的大小:

这应该说明带有裸片的晶圆(半导体行业)

所以我明白我需要在 XAML 中使用 <Path> 来构造“带缺口的圆”

我的问题是我无法将ArcSegment 元素绑定到CustomControl 的SizeArcSegment 具有 Size 属性,CustomControl 具有 ActualWidthActualHeight。我尝试了几种方法,但它们都不适合我。

这是我为CustomControl 上课的:

    public class WaferMap : Control
    {
        public static readonly DependencyProperty ActualSizeProperty = DependencyProperty.Register(
            nameof(ActualSize), typeof(Size), typeof(WaferMap), new PropertyMetadata(default(Size)));

        public Size ActualSize
        {
            get => (Size) this.GetValue(ActualSizeProperty);
            set => this.SetValue(ActualSizeProperty, value);
        }

        public WaferMap()
        {
            var actualWidthPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ActualWidthProperty, typeof(WaferMap));
            actualWidthPropertyDescriptor.AddValueChanged(this, OnActualWidthOrHeightChanged);

            var actualHeightPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(ActualHeightProperty, typeof(WaferMap));
            actualHeightPropertyDescriptor.AddValueChanged(this, OnActualWidthOrHeightChanged);
        }

        private void OnActualWidthOrHeightChanged(object? sender, EventArgs e)
        {
            this.ActualSize = new Size(ActualWidth, ActualHeight);
        }

        static WaferMap()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(WaferMap), new FrameworkPropertyMetadata(typeof(WaferMap)));
        }
    }

以及我用于它的 XAML 样式:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Zeiss.CdAnalizer.Ui">
    <Style TargetType="local:WaferMap">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:WaferMap" >
                    <ControlTemplate.Resources>
                        <local:WaferMap x:Key="WaferMap"/>
                    </ControlTemplate.Resources>
                    <Grid DataContext="{Binding Source={StaticResource WaferMap}}">
                        <Path Stroke="Black" StrokeThickness="1">
                            <Path.Data>
                                <PathGeometry>
                                    <PathGeometry.Figures>
                                        <PathFigureCollection>
                                            <PathFigure StartPoint="145,300">
                                                <PathFigure.Segments>
                                                    <PathSegmentCollection>
                                                        <ArcSegment 
                                                            IsLargeArc="True"
                                                            Size="{Binding Path=ActualSize, PresentationTraceSources.TraceLevel=High}"
                                                            SweepDirection="Clockwise"
                                                            Point="155,300" />
                                                    </PathSegmentCollection>
                                                </PathFigure.Segments>
                                            </PathFigure>
                                        </PathFigureCollection>
                                    </PathGeometry.Figures>
                                </PathGeometry>
                            </Path.Data>
                        </Path>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style></ResourceDictionary>

当然,我还需要绑定StartPoint,但首先我想看看那些简单的东西对我有用。不幸的是,事实并非如此。我在输出窗口中看到了这个:

System.Windows.Data Warning: 60 : BindingExpression (hash=14976165): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=14976165): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=14976165): Attach to System.Windows.Media.ArcSegment.Size (hash=24211521)
System.Windows.Data Warning: 64 : BindingExpression (hash=14976165): Use Framework mentor <null>
System.Windows.Data Warning: 67 : BindingExpression (hash=14976165): Resolving source 
System.Windows.Data Warning: 69 : BindingExpression (hash=14976165): Framework mentor not found
System.Windows.Data Warning: 65 : BindingExpression (hash=14976165): Resolve source deferred
System.Windows.Data Warning: 95 : BindingExpression (hash=14976165): Got InheritanceContextChanged event from ArcSegment (hash=24211521)
System.Windows.Data Warning: 67 : BindingExpression (hash=14976165): Resolving source 
System.Windows.Data Warning: 69 : BindingExpression (hash=14976165): Framework mentor not found
System.Windows.Data Warning: 95 : BindingExpression (hash=14976165): Got InheritanceContextChanged event from ArcSegment (hash=24211521)
System.Windows.Data Warning: 67 : BindingExpression (hash=14976165): Resolving source 
System.Windows.Data Warning: 69 : BindingExpression (hash=14976165): Framework mentor not found
System.Windows.Data Warning: 95 : BindingExpression (hash=14976165): Got InheritanceContextChanged event from ArcSegment (hash=24211521)
System.Windows.Data Warning: 67 : BindingExpression (hash=14976165): Resolving source 
System.Windows.Data Warning: 69 : BindingExpression (hash=14976165): Framework mentor not found
System.Windows.Data Warning: 95 : BindingExpression (hash=14976165): Got InheritanceContextChanged event from ArcSegment (hash=24211521)
System.Windows.Data Warning: 67 : BindingExpression (hash=14976165): Resolving source 
System.Windows.Data Warning: 69 : BindingExpression (hash=14976165): Framework mentor not found
System.Windows.Data Warning: 95 : BindingExpression (hash=14976165): Got InheritanceContextChanged event from ArcSegment (hash=24211521)
System.Windows.Data Warning: 67 : BindingExpression (hash=14976165): Resolving source 
System.Windows.Data Warning: 70 : BindingExpression (hash=14976165): Found data context element: Path (hash=10232270) (OK)
System.Windows.Data Warning: 78 : BindingExpression (hash=14976165): Activate with root item WaferMap (hash=14353717)
System.Windows.Data Warning: 108 : BindingExpression (hash=14976165):   At level 0 - for WaferMap.ActualSize found accessor DependencyProperty(ActualSize)
System.Windows.Data Warning: 104 : BindingExpression (hash=14976165): Replace item at level 0 with WaferMap (hash=14353717), using accessor DependencyProperty(ActualSize)
System.Windows.Data Warning: 101 : BindingExpression (hash=14976165): GetValue at level 0 from WaferMap (hash=14353717) using DependencyProperty(ActualSize): Size (hash=0)
System.Windows.Data Warning: 80 : BindingExpression (hash=14976165): TransferValue - got raw value Size (hash=0)
System.Windows.Data Warning: 89 : BindingExpression (hash=14976165): TransferValue - using final value Size (hash=0)

当我说它不起作用时 = 当我更改表单的大小时,什么也没有发生(弧线保持相同的小破折号)。 此外,WaferMap.ActualSize.get 永远不会被调用。当我更改表单的大小时调用 setter(如您所见,我已注册更改 ActualWidthActualHeight 的事件)。

谢谢!

【问题讨论】:

  • local:WaferMap 的 ControlTemplate 中拥有 &lt;local:WaferMap x:Key="WaferMap"/&gt; 资源完全没有意义。您正在使用一个 WaferMap 作为另一个 WaferMap 的 DataContext,即模板化的。
  • 形状有变化吗?或者它总是一个有缺口的圆圈?如果它是恒定的,您可以构建一个几何图形并将其作为资源字典中的资源。使用该几何图形作为路径的数据,并将其拉伸到路径或路径容器的任何大小。
  • @Clemens,如果我删除它,以下行 Grid DataContext=... 将失败,因为它找不到 WaferMap... 我也应该删除它吗?
  • 不需要设置任何DataContext,使用TemplateBindings即可。但是,似乎不清楚为什么您不只是从 Shape 类派生。

标签: c# wpf xaml binding


【解决方案1】:

您也许可以使用如下所示的简单派生形状。

它在底部中心绘制一个带有缺口的ArcSegment,您所要做的就是调整缺口的大小。

public class WaferMap : Shape
{
    private readonly StreamGeometry geometry = new StreamGeometry();

    protected override Geometry DefiningGeometry => geometry;

    protected override Size MeasureOverride(Size size)
    {
        if (double.IsInfinity(size.Width))
        {
            size.Width = StrokeThickness;
        }

        if (double.IsInfinity(size.Height))
        {
            size.Height = StrokeThickness;
        }

        return size;
    }

    protected override Size ArrangeOverride(Size size)
    {
        var x = size.Width / 2;
        var y = size.Height - StrokeThickness / 2;
        var arcSize = new Size(
            (size.Width - StrokeThickness) / 2, (size.Height - StrokeThickness) / 2);

        using (var sgc = geometry.Open())
        {
            sgc.BeginFigure(new Point(x, y - 20), true, true);
            sgc.LineTo(new Point(x - 10, y), true, true);
            sgc.ArcTo(new Point(x + 10, y), arcSize, 0, true,
                      SweepDirection.Clockwise, true, true);
        }

        return size;
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        drawingContext.DrawGeometry(Fill, new Pen(Stroke, StrokeThickness), geometry);
    }
}

您可以像使用任何其他 Shape 元素一样使用它:

<local:WaferMap Stroke="Orange" StrokeThickness="3" Margin="10"/>

【讨论】:

  • 谢谢!我认为 XAML 的全部目的是定义所有这些与演示相关的功能。并且只在代码中保留真正起作用的“真实”功能
  • 刚刚找到了对 Clemens 解决方案的解释。太糟糕了,我在最初搜索一周后就到达了它:markheath.net/post/creating-resizable-shape-controls-in
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多