Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在c#wpf中检查元素是否脱离其父元素_C#_Wpf_Canvas_Geometry_Shapes - Fatal编程技术网

如何在c#wpf中检查元素是否脱离其父元素

如何在c#wpf中检查元素是否脱离其父元素,c#,wpf,canvas,geometry,shapes,C#,Wpf,Canvas,Geometry,Shapes,我在运行时在我的应用程序的画布上创建形状,除了所有的形状外,椭圆正在离开画布。如何将其限制为画布?由于顶点处的控制点,所有其他形状都包含在画布中。我如何保持一个检查,不让椭圆走出画布没有剪辑。我使用了ClipToBounds,但它不符合我的需要 另外,另一种解决方案是,如果我可以在radiusX属性的椭圆左侧添加一个控制点。我不能在椭圆上的半径X的左侧添加控制点。如果你能帮我的话 radiusXcp = new ControlPoint(this, EllipseGeom, Ellipse

我在运行时在我的应用程序的画布上创建形状,除了所有的形状外,椭圆正在离开画布。如何将其限制为画布?由于顶点处的控制点,所有其他形状都包含在画布中。我如何保持一个检查,不让椭圆走出画布没有剪辑。我使用了ClipToBounds,但它不符合我的需要

另外,另一种解决方案是,如果我可以在radiusX属性的椭圆左侧添加一个控制点。我不能在椭圆上的半径X的左侧添加控制点。如果你能帮我的话

   radiusXcp = new ControlPoint(this, EllipseGeom, EllipseGeometry.RadiusYProperty, 1, true, false);
        radiusXcp.RelativeTo = EllipseGeometry.CenterProperty;
        shape_ControlPoints.Add(radiusXcp);

        radiusXcp = new ControlPoint(this, EllipseGeom, EllipseGeometry.RadiusXProperty, 0, true, false);
        radiusXcp.RelativeTo = EllipseGeometry.CenterProperty;
        shape_ControlPoints.Add(radiusXcp);

        //EllipseGeom.RadiusX = -EllipseGeom.RadiusX;

        //radiusXcp = new ControlPoint(this, EllipseGeom, EllipseGeometry.RadiusXProperty, 0, true, false);
        //radiusXcp.RelativeTo =  EllipseGeometry.CenterProperty;
        //shape_ControlPoints.Add(radiusXcp);

        //EllipseGeom.RadiusX = -EllipseGeom.RadiusX;

下面是我将要做的一个快速示例。可以对其进行改进,代码的编写主要是为了易于阅读和理解。它也不能处理形状大小是否大于画布的可能性(不确定这是否是项目中的用例)。 例如,我在画布上使用了“Loaded”事件来重置绘图前的位置。在绘制椭圆对象之前,需要进行此检查

private void TestCanvas_Loaded(object sender, RoutedEventArgs e)
{
    //canvas = 450 x 800
    Ellipse test_ellipse = new Ellipse();
    test_ellipse.Width = 100;
    test_ellipse.Height = 100;
    test_ellipse.Fill = Brushes.Red;
    Canvas.SetLeft(test_ellipse, 700);
    Canvas.SetTop(test_ellipse, -500);
    Reset_Ellipse_Bounds(TestCanvas, ref test_ellipse);
    TestCanvas.Children.Add(test_ellipse);
}

private void Reset_Ellipse_Bounds(Canvas myCanvas, ref Ellipse myEllipse)
{
    var left = Canvas.GetLeft(myEllipse);
    var top = Canvas.GetTop(myEllipse);

    //handle too far right
    if (left + myEllipse.Width > myCanvas.ActualWidth)
        Canvas.SetLeft(myEllipse, myCanvas.ActualWidth - myEllipse.Width);
    //handle too far left
    if(left < 0)
        Canvas.SetLeft(myEllipse, 0);
    //handle too far up
    if (top < 0)
        Canvas.SetTop(myEllipse, 0);
    //handle too far down
    if (top + myEllipse.Height > myCanvas.ActualHeight)
        Canvas.SetTop(myEllipse, myCanvas.ActualHeight - myEllipse.Height);
}
private void TestCanvas\u已加载(对象发送方,RoutedEventArgs e)
{
//画布=450 x 800
椭圆测试_椭圆=新椭圆();
测试椭圆宽度=100;
试验高度=100;
test_椭圆填充=刷子红色;
Canvas.SetLeft(test_椭圆,700);
画布.机顶盒(测试椭圆,-500);
重置椭圆边界(TestCanvas,ref test_Ellipse);
TestCanvas.Children.Add(test_椭圆);
}
私有无效重置\椭圆\边界(画布myCanvas,参考椭圆myEllipse)
{
var left=Canvas.GetLeft(myEllipse);
var top=Canvas.GetTop(myEllipse);
//操作过右
如果(左+myEllipse.Width>myCanvas.ActualWidth)
SetLeft(myEllipse,myCanvas.ActualWidth-myEllipse.Width);
//把手太左了
if(左<0)
Canvas.SetLeft(myEllipse,0);
//处理得太过分
如果(顶部<0)
Canvas.SetTop(myEllipse,0);
//把手放得太低
如果(顶部+myEllipse.Height>myCanvas.ActualHeight)
SetTop(myEllipse,myCanvas.ActualHeight-myEllipse.Height);
}
为了确保XAML的完整性:

 <Grid>
    <Canvas x:Name="TestCanvas" Loaded="TestCanvas_Loaded" />
 </Grid>

其思想是对照画布边缘检查边界框。有很多方法可以改进这一点,但我认为最简单的解决方案更容易遵循


在每个if语句中,您可以添加更多的逻辑或方法来进行进一步的处理,但这应该可以回答知道它是否在父语句之外的一般问题

下面是一个我将要做的快速示例。可以对其进行改进,代码的编写主要是为了易于阅读和理解。它也不能处理形状大小是否大于画布的可能性(不确定这是否是项目中的用例)。 例如,我在画布上使用了“Loaded”事件来重置绘图前的位置。在绘制椭圆对象之前,需要进行此检查

private void TestCanvas_Loaded(object sender, RoutedEventArgs e)
{
    //canvas = 450 x 800
    Ellipse test_ellipse = new Ellipse();
    test_ellipse.Width = 100;
    test_ellipse.Height = 100;
    test_ellipse.Fill = Brushes.Red;
    Canvas.SetLeft(test_ellipse, 700);
    Canvas.SetTop(test_ellipse, -500);
    Reset_Ellipse_Bounds(TestCanvas, ref test_ellipse);
    TestCanvas.Children.Add(test_ellipse);
}

private void Reset_Ellipse_Bounds(Canvas myCanvas, ref Ellipse myEllipse)
{
    var left = Canvas.GetLeft(myEllipse);
    var top = Canvas.GetTop(myEllipse);

    //handle too far right
    if (left + myEllipse.Width > myCanvas.ActualWidth)
        Canvas.SetLeft(myEllipse, myCanvas.ActualWidth - myEllipse.Width);
    //handle too far left
    if(left < 0)
        Canvas.SetLeft(myEllipse, 0);
    //handle too far up
    if (top < 0)
        Canvas.SetTop(myEllipse, 0);
    //handle too far down
    if (top + myEllipse.Height > myCanvas.ActualHeight)
        Canvas.SetTop(myEllipse, myCanvas.ActualHeight - myEllipse.Height);
}
private void TestCanvas\u已加载(对象发送方,RoutedEventArgs e)
{
//画布=450 x 800
椭圆测试_椭圆=新椭圆();
测试椭圆宽度=100;
试验高度=100;
test_椭圆填充=刷子红色;
Canvas.SetLeft(test_椭圆,700);
画布.机顶盒(测试椭圆,-500);
重置椭圆边界(TestCanvas,ref test_Ellipse);
TestCanvas.Children.Add(test_椭圆);
}
私有无效重置\椭圆\边界(画布myCanvas,参考椭圆myEllipse)
{
var left=Canvas.GetLeft(myEllipse);
var top=Canvas.GetTop(myEllipse);
//操作过右
如果(左+myEllipse.Width>myCanvas.ActualWidth)
SetLeft(myEllipse,myCanvas.ActualWidth-myEllipse.Width);
//把手太左了
if(左<0)
Canvas.SetLeft(myEllipse,0);
//处理得太过分
如果(顶部<0)
Canvas.SetTop(myEllipse,0);
//把手放得太低
如果(顶部+myEllipse.Height>myCanvas.ActualHeight)
SetTop(myEllipse,myCanvas.ActualHeight-myEllipse.Height);
}
为了确保XAML的完整性:

 <Grid>
    <Canvas x:Name="TestCanvas" Loaded="TestCanvas_Loaded" />
 </Grid>

其思想是对照画布边缘检查边界框。有很多方法可以改进这一点,但我认为最简单的解决方案更容易遵循


在每个if语句中,您可以添加更多的逻辑或方法来进行进一步的处理,但这应该可以回答知道它是否在父语句之外的一般问题

只需将
ClipToBounds=“true”
设置为其父控件,即可避免在其外部绘制画布

在我的例子中,我将其设置为Grid,如下所示:

<Grid x:Name="MainGrid" Background="WhiteSmoke" ClipToBounds="true">
    <Canvas Margin="10" Background="Transparent"
    SizeChanged="ViewportSizeChanged"
    MouseLeftButtonDown="ViewportMouseLeftButtonDown"
    MouseLeftButtonUp="ViewportMouseLeftButtonUp"
    MouseMove="ViewportMouseMove"
    MouseWheel="ViewportMouseWheel">

        <Canvas x:Name="canvas" Width="1000" Height="600"
        HorizontalAlignment="Left" VerticalAlignment="Top">
            <Canvas.RenderTransform>
                <MatrixTransform x:Name="transform"/>
            </Canvas.RenderTransform>
        </Canvas>

        <Canvas x:Name="canvas2" Width="1000" Height="600"
        HorizontalAlignment="Left" VerticalAlignment="Top">
            <Canvas.RenderTransform>
                <MatrixTransform x:Name="transform2"/>
            </Canvas.RenderTransform>
        </Canvas>
    </Canvas>
</Grid>

只需将
cliptobunds=“true”
设置为其父控件,即可避免在其外绘制画布

在我的例子中,我将其设置为Grid,如下所示:

<Grid x:Name="MainGrid" Background="WhiteSmoke" ClipToBounds="true">
    <Canvas Margin="10" Background="Transparent"
    SizeChanged="ViewportSizeChanged"
    MouseLeftButtonDown="ViewportMouseLeftButtonDown"
    MouseLeftButtonUp="ViewportMouseLeftButtonUp"
    MouseMove="ViewportMouseMove"
    MouseWheel="ViewportMouseWheel">

        <Canvas x:Name="canvas" Width="1000" Height="600"
        HorizontalAlignment="Left" VerticalAlignment="Top">
            <Canvas.RenderTransform>
                <MatrixTransform x:Name="transform"/>
            </Canvas.RenderTransform>
        </Canvas>

        <Canvas x:Name="canvas2" Width="1000" Height="600"
        HorizontalAlignment="Left" VerticalAlignment="Top">
            <Canvas.RenderTransform>
                <MatrixTransform x:Name="transform2"/>
            </Canvas.RenderTransform>
        </Canvas>
    </Canvas>
</Grid>


您可以将画布放在
网格中
并设置网格控件的
cliptobunds
属性。确保正确设置网格的宽度和高度。您能设置椭圆的最大半径吗?基于中心点到画布边缘的距离?并将中心限制为仅在画布内。我会使用某种“检查”方法来测试边界。据我所知,我从未遇到过没有解决方案的内置解决方案。@rashmatash有什么方法可以检查我的几何体的路径是否超出视觉边界或将其限制在视觉边界内吗?@Gingernija有什么方法可以检查我的几何体的路径是否超出视觉边界或将其限制在视觉边界内吗?你可以把画布放进去a
Grid
并设置Grid控件的
cliptobunds
属性。确保适当设置网格的宽度和高度。您能设置最大半径吗