裁剪到WPF中的一个路径 [英] Clipping to a Path in WPF

查看:117
本文介绍了裁剪到WPF中的一个路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建WPF用户控件,它允许用户选择鞋的特定区域(脚跟,边,鞋底等)



我们的想法是你有鞋,你可以对单个零件单击并选择区域的图像(图)。



我使用了一组复选框这些模板。



有与限定的边缘,然后一组限定了个别地区矩形的路径的单个复选框





这工作得很好,除了显然并不好看。为了使它看起来更好,我想隐藏的一切,是不是原来的鞋子路径内。



的矩形都在网格中一个单独的行和背景鞋跨度。所有的行



我试图设置父网格为背景靴边相同的路径的剪辑属性,但得到了一些怪异的结果:





我敢肯定,我在右边线与电网裁剪,但我不明白正在发生的事情在这里。



如果任何人都可以使用此问题的帮助或建议做同样任务的一个更好的方式,我将不胜感激。

 <几何X:键=ShoeEdgeGeometry> M26.25,0.5 C40.471332,0.5 52,17.625107 52,38.75 52,51.292905 47.935695,62.425729 41.656635,69.401079 L41.349452,69.733874 42.012107,70.457698 C45.421829,74.364614 47.5,79.554564 47.5,85.25 47.5,97.400265 38.042015,107.25 26.375,107.25 14.707984,107.25 5.2499995,97.400265 5.2499991,85.25 5.2499995,79.554564 7.3281701,74.364614 10.737891,70.457698 L11 .276058,69.869853 10.843364,69.401079 C4.5643053,62.425729 0.49999952,51.292905 0.5,38.75 0.49999952,17.625107 12.028667,0.5 26.25,0.5 z,其中; /几何与GT; 



<电网保证金=0
剪辑={StaticResource的ShoeEdgeGeometry}>
< Grid.RowDefinitions>
< RowDefinition HEIGHT =2 */>
< RowDefinition HEIGHT =4 */>
< RowDefinition HEIGHT =2 */>
< RowDefinition HEIGHT =2 */>
< RowDefinition HEIGHT =2 */>
< /Grid.RowDefinitions>
<! - 边缘复选框 - >
<复选框X:NAME =ShoeEdgeRegion
Grid.Row =0
Grid.RowSpan =5>
< CheckBox.Style>
<风格的TargetType =复选框>
< setter属性=光标
值=手/>
< setter属性=模板>
< Setter.Value>
<的ControlTemplate的TargetType ={X:类型的CheckBox}>
<网格和GT;
<路径X:NAME =主路径
数据={StaticResource的ShoeEdgeGeometry}
填充={StaticResource的TransparentBrush}
行程=黑
=拉伸填充/>
< /网格和GT;
< ControlTemplate.Triggers>
<触发属性=器isChecked
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=IsMouseOver
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
< /ControlTemplate.Triggers>
< /控件模板>
< /Setter.Value>
< /二传手>
< /样式和GT;
< /CheckBox.Style>
< /复选框>
<! - 脚趾复选框 - >
<复选框X:NAME =ShoeToeRegion
Grid.Row =0>
< CheckBox.Style>
<风格的TargetType =复选框>
< setter属性=光标
值=手/>
< setter属性=模板>
< Setter.Value>
<的ControlTemplate的TargetType ={X:类型的CheckBox}>
<网格和GT;
将;矩形X:名称=MainPath的
StrokeThickness =1
填充={StaticResource的TransparentBrush}
行程=黑/>
< /网格和GT;
< ControlTemplate.Triggers>
<触发属性=器isChecked
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=IsMouseOver
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=器isChecked
值=真>
<二传手的TargetName =主路径
属性=填充
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=IsMouseOver
值=真>
<二传手的TargetName =主路径
属性=填充
值={StaticResource的RedBrush}/>
< /触发>
< /ControlTemplate.Triggers>
< /控件模板>
< /Setter.Value>
< /二传手>
< /样式和GT;
< /CheckBox.Style>
< /复选框>
<! - 唯一的复选框 - >
将;复选框X:名称=ShoeSoleRegion
Grid.Row =1
保证金=0,-1,0,0>
< CheckBox.Style>
<风格的TargetType =复选框>
< setter属性=光标
值=手/>
< setter属性=模板>
< Setter.Value>
<的ControlTemplate的TargetType ={X:类型的CheckBox}>
<网格和GT;
将;矩形X:名称=MainPath的
StrokeThickness =1
填充={StaticResource的TransparentBrush}
行程=黑/>
< /网格和GT;
< ControlTemplate.Triggers>
<触发属性=器isChecked
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=IsMouseOver
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=器isChecked
值=真>
<二传手的TargetName =主路径
属性=填充
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=IsMouseOver
值=真>
<二传手的TargetName =主路径
属性=填充
值={StaticResource的RedBrush}/>
< /触发>
< /ControlTemplate.Triggers>
< /控件模板>
< /Setter.Value>
< /二传手>
< /样式和GT;
< /CheckBox.Style>
< /复选框>
<! - 脚背复选框 - >
<复选框X:NAME =ShoeInstepRegion
保证金=0,-1,0,0
Grid.Row =2>
< CheckBox.Style>
<风格的TargetType =复选框>
< setter属性=光标
值=手/>
< setter属性=模板>
< Setter.Value>
<的ControlTemplate的TargetType ={X:类型的CheckBox}>
<网格和GT;
将;矩形X:名称=MainPath的
StrokeThickness =1
填充={StaticResource的TransparentBrush}
行程=黑/>
< /网格和GT;
< ControlTemplate.Triggers>
<触发属性=器isChecked
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=IsMouseOver
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=器isChecked
值=真>
<二传手的TargetName =主路径
属性=填充
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=IsMouseOver
值=真>
<二传手的TargetName =主路径
属性=填充
值={StaticResource的RedBrush}/>
< /触发>
< /ControlTemplate.Triggers>
< /控件模板>
< /Setter.Value>
< /二传手>
< /样式和GT;
< /CheckBox.Style>
< /复选框>
<! - 下后跟复选框 - >
<复选框X:NAME =ShoeLowerHeelRegion
Grid.Row =3
保证金=0,-1,0,0>
< CheckBox.Style>
<风格的TargetType =复选框>
< setter属性=光标
值=手/>
< setter属性=模板>
< Setter.Value>
<的ControlTemplate的TargetType ={X:类型的CheckBox}>
<网格和GT;
将;矩形X:名称=MainPath的
StrokeThickness =1
填充={StaticResource的TransparentBrush}
行程=黑/>
< /网格和GT;
< ControlTemplate.Triggers>
<触发属性=器isChecked
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=IsMouseOver
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=器isChecked
值=真>
<二传手的TargetName =主路径
属性=填充
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=IsMouseOver
值=真>
<二传手的TargetName =主路径
属性=填充
值={StaticResource的RedBrush}/>
< /触发>
< /ControlTemplate.Triggers>
< /控件模板>
< /Setter.Value>
< /二传手>
< /样式和GT;
< /CheckBox.Style>
< /复选框>
<! - 脚跟复选框 - >
<复选框X:NAME =ShoeHeelRegion
Grid.Row =4
保证金=0,-1,0,0>
< CheckBox.Style>
<风格的TargetType =复选框>
< setter属性=光标
值=手/>
< setter属性=模板>
< Setter.Value>
<的ControlTemplate的TargetType ={X:类型的CheckBox}>
<网格和GT;
将;矩形X:名称=MainPath的
StrokeThickness =1
填充={StaticResource的TransparentBrush}
行程=黑/>
< /网格和GT;
< ControlTemplate.Triggers>
<触发属性=器isChecked
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=IsMouseOver
值=真>
<二传手的TargetName =主路径
属性=中风
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=器isChecked
值=真>
<二传手的TargetName =主路径
属性=填充
值={StaticResource的RedBrush}/>
< /触发>
<触发属性=IsMouseOver
值=真>
<二传手的TargetName =主路径
属性=填充
值={StaticResource的RedBrush}/>
< /触发>
< /ControlTemplate.Triggers>
< /控件模板>
< /Setter.Value>
< /二传手>
< /样式和GT;
< /CheckBox.Style>
< /复选框>
< /网格和GT;


解决方案

诊断



此基础上您所提供我转载您所描述的问题的代码。我们假设网格是大小的 100×200 。首先,这里的网格的外观并没有用夹子集:






显然,结果是一样的。但这里是它的外观,如果我们添加一些背景到网格(红色网格的背景,和蓝色的背景是背后的网格):



< A HREF =http://i.stack.imgur.com/DGQyx.png>



现在,我们可以清楚地看到这里发生了什么 - 几何(大致尺寸<强> 50×)没有自动缩放到网格的大小,而是它的原始尺寸保持,从而剪裁一大堆更多,我们想。下面是它的外观一样,如果我们调整网格的大小相匹配的几何尺寸:





预赛



为了使我们的工作更容易一点我已经提取的几何图形定义的资源和规范化,以便它是大小< STRONG>的1x1 ,这将使缩放轻松很多。因此,这里的资源:

 < PathFigureCollection X:键=ShoeEdgeFigures> 
M 0.5048,0
C 0.7783,0 1,0.164 1,0.361 1,0.478 0.9218,0.582 0.8011,0.647
大号0.7952,0.65 0.8079,0.657
C 0.8735,0.693 0.9135,0.742 0.9135,0.795 0.9135,0.908 0.7316,1 0.5072,1
0.2828,1 0.101,0.908 0.101,0.795 0.101,0.742 0.1409,0.693 0.2065,0.657
大号0.2168,0.651 0.2085,0.647
C 0.0878,0.582 0,0.478 0,0.361 0,0.164 0.2313,0 0.5048,0
Z
< / PathFigureCollection>
<的PathGeometry X:键=ShoeEdgeGeometry图={StaticResource的ShoeEdgeFigures}/>



SOLUTION



为了使格看如我们预期,我们将需要扩展几何 - 这可以通过 Geometry.Transform 属性来完成。我认为这是有益的定义新的几何用于这一目的。然后,我们只需要设置 ScaleTransform 的ScaleX 的scaleY 分别等于网格的宽度和高度。这是因为几何形状的初始大小的的1x1 。下面的代码:

 <电网WIDTH =100HEIGHT =200(...)> 
< Grid.Resources>
<的PathGeometry X:键=StaticClipGeometry图={StaticResource的ShoeEdgeFigures}>
< PathGeometry.Transform>
< ScaleTransform的ScaleX =100的scaleY =200/>
< /PathGeometry.Transform>
< /&的PathGeometry GT;
< /Grid.Resources>
< Grid.Clip>
<静态资源的ResourceKey =StaticClipGeometry/>
< /Grid.Clip>
(...)
< /网格和GT;

此然而有所限制,因为网格的大小需要是常数,并在之前编制已知时间。



为使剪辑的几何形状调整到网格的大小动态我们需要绑定 Geometry.Transform 属性,因为我们将结合这两个 Grid.ActualWidth Grid.ActualHeight ,我们要需要一个简单的转换:

 公共类SizeToScaleConverter:IMultiValueConverter 
{
公共对象转换(对象[]值,类型TARGETTYPE,对象参数,CultureInfo的文化)
{
返回新ScaleTransform
{
的ScaleX =(双)值[0],
的scaleY =(双)值[1​​],
};
}

公共对象[] ConvertBack(对象的值,类型[] targetTypes,对象参数,CultureInfo的文化)
{
抛出新NotImplementedException();
}
}



然后我们定义网格:

 <网格(...)> 
< Grid.Resources>
<的PathGeometry X:键=DynamicClipGeometry图={StaticResource的ShoeEdgeFigures}>
< PathGeometry.Transform>
< MultiBinding>
< MultiBinding.Converter>
<局部:SizeToScaleConverter />
< /MultiBinding.Converter>
<绑定的RelativeSource ={的RelativeSource AncestorType =电网}
路径=ActualWidth的/>
<绑定的RelativeSource ={的RelativeSource AncestorType =电网}
路径=的ActualHeight/>
< / MultiBinding>
< /PathGeometry.Transform>
< /&的PathGeometry GT;
< /Grid.Resources>
< Grid.Clip>
<静态资源的ResourceKey =DynamicClipGeometry/>
< /Grid.Clip>
(...)
< /网格和GT;

和最终的结果是这样的:




I am attempting to create a user control in WPF that allows the user to select specific regions of a shoe (heel, edge, sole etc)

The idea is that you have an image (drawing) of a shoe which you can click on individual parts and select the regions.

I am using a set of check boxes which are templated.

There is a single check box with a path that defines the edge and then a set of rectangles which define the individual areas.

This works well except obviously it doesn't look good. To make it look better I want to hide everything that is not inside the original shoe path.

The rectangles are all on a seperate row in a grid and the background shoe spans all of the rows.

I tried to set the Clip property of the parent grid to the same path as the background shoe edge but got some weird results:

I am pretty sure I am on the right lines with the Grid clipping but I dont understand what is happening here.

If anybody can help with this issue or suggest a better way of doing the same task I would be grateful.

<Geometry x:Key="ShoeEdgeGeometry">M26.25,0.5 C40.471332,0.5 52,17.625107 52,38.75 52,51.292905 47.935695,62.425729 41.656635,69.401079 L41.349452,69.733874 42.012107,70.457698 C45.421829,74.364614 47.5,79.554564 47.5,85.25 47.5,97.400265 38.042015,107.25 26.375,107.25 14.707984,107.25 5.2499995,97.400265 5.2499991,85.25 5.2499995,79.554564 7.3281701,74.364614 10.737891,70.457698 L11.276058,69.869853 10.843364,69.401079 C4.5643053,62.425729 0.49999952,51.292905 0.5,38.75 0.49999952,17.625107 12.028667,0.5 26.25,0.5 z</Geometry>



 <Grid Margin="0"
          Clip="{StaticResource ShoeEdgeGeometry}">
        <Grid.RowDefinitions>
            <RowDefinition Height="2*" />
            <RowDefinition Height="4*" />
            <RowDefinition Height="2*" />
            <RowDefinition Height="2*" />
            <RowDefinition Height="2*" />
        </Grid.RowDefinitions>
        <!-- The edge check box-->
        <CheckBox x:Name="ShoeEdgeRegion"
                  Grid.Row="0"
                  Grid.RowSpan="5">
            <CheckBox.Style>
                <Style TargetType="CheckBox">
                    <Setter Property="Cursor"
                            Value="Hand" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type CheckBox}">
                                <Grid>
                                    <Path x:Name="MainPath"
                                          Data="{StaticResource ShoeEdgeGeometry}"
                                          Fill="{StaticResource TransparentBrush}"
                                          Stroke="Black"
                                          Stretch="Fill" />
                                </Grid>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsChecked"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsMouseOver"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </CheckBox.Style>
        </CheckBox>
        <!-- The Toe check box-->
        <CheckBox x:Name="ShoeToeRegion"
                  Grid.Row="0">
            <CheckBox.Style>
                <Style TargetType="CheckBox">
                    <Setter Property="Cursor"
                            Value="Hand" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type CheckBox}">
                                <Grid>
                                    <Rectangle x:Name="MainPath"
                                               StrokeThickness="1"
                                               Fill="{StaticResource TransparentBrush}"
                                               Stroke="Black" />
                                </Grid>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsChecked"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsMouseOver"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsChecked"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Fill"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsMouseOver"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Fill"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </CheckBox.Style>
        </CheckBox>
        <!-- The Sole check box-->
        <CheckBox x:Name="ShoeSoleRegion"
                  Grid.Row="1"
                  Margin="0,-1,0,0">
            <CheckBox.Style>
                <Style TargetType="CheckBox">
                    <Setter Property="Cursor"
                            Value="Hand" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type CheckBox}">
                                <Grid>
                                    <Rectangle x:Name="MainPath"
                                               StrokeThickness="1"
                                               Fill="{StaticResource TransparentBrush}"
                                               Stroke="Black" />
                                </Grid>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsChecked"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsMouseOver"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsChecked"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Fill"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsMouseOver"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Fill"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </CheckBox.Style>
        </CheckBox>
        <!-- The Instep check box-->
        <CheckBox x:Name="ShoeInstepRegion"
                  Margin="0,-1,0,0"
                  Grid.Row="2">
            <CheckBox.Style>
                <Style TargetType="CheckBox">
                    <Setter Property="Cursor"
                            Value="Hand" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type CheckBox}">
                                <Grid>
                                    <Rectangle x:Name="MainPath"
                                               StrokeThickness="1"
                                               Fill="{StaticResource TransparentBrush}"
                                               Stroke="Black" />
                                </Grid>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsChecked"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsMouseOver"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsChecked"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Fill"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsMouseOver"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Fill"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </CheckBox.Style>
        </CheckBox>
        <!-- The Lower heel check box-->
        <CheckBox x:Name="ShoeLowerHeelRegion"
                  Grid.Row="3"
                  Margin="0,-1,0,0">
            <CheckBox.Style>
                <Style TargetType="CheckBox">
                    <Setter Property="Cursor"
                            Value="Hand" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type CheckBox}">
                                <Grid>
                                    <Rectangle x:Name="MainPath"
                                               StrokeThickness="1"
                                               Fill="{StaticResource TransparentBrush}"
                                               Stroke="Black" />
                                </Grid>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsChecked"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsMouseOver"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsChecked"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Fill"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsMouseOver"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Fill"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </CheckBox.Style>
        </CheckBox>
        <!-- The heel check box-->
        <CheckBox x:Name="ShoeHeelRegion"
                  Grid.Row="4"
                  Margin="0,-1,0,0">
            <CheckBox.Style>
                <Style TargetType="CheckBox">
                    <Setter Property="Cursor"
                            Value="Hand" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type CheckBox}">
                                <Grid>
                                    <Rectangle x:Name="MainPath"
                                               StrokeThickness="1"
                                               Fill="{StaticResource TransparentBrush}"
                                               Stroke="Black" />
                                </Grid>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsChecked"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsMouseOver"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Stroke"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsChecked"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Fill"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                    <Trigger Property="IsMouseOver"
                                             Value="True">
                                        <Setter TargetName="MainPath"
                                                Property="Fill"
                                                Value="{StaticResource RedBrush}" />
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </CheckBox.Style>
        </CheckBox>
    </Grid>

解决方案

DIAGNOSIS

Basing on the code you've provided I've reproduced the issue you described. We'll assume that the grid is of size 100x200. First of all, here's how the grid looks without and with clip set:

Obviously the result is the same. But here's how it looks if we add some background to the grid (red is the background of the grid, and blue is the background "behind" the grid):

Now we can clearly see what happened here - the geometry (roughly of size 50x100) was not automatically scaled to the size of the grid, but rather it's original size was maintained, thus clipping whole lot more that we'd like. Here's how it looks like if we resize the grid to match the size of the geometry:

PRELIMINARIES

In order to make our work a bit easier I've extracted the geometry figure definition to a resource and normalized it so that it is of size 1x1, which will make scaling a lot easier. So here are the resources:

<PathFigureCollection x:Key="ShoeEdgeFigures">
    M 0.5048,0
    C 0.7783,0 1,0.164 1,0.361 1,0.478 0.9218,0.582 0.8011,0.647
    L 0.7952,0.65 0.8079,0.657
    C 0.8735,0.693 0.9135,0.742 0.9135,0.795 0.9135,0.908 0.7316,1 0.5072,1
      0.2828,1 0.101,0.908 0.101,0.795 0.101,0.742 0.1409,0.693 0.2065,0.657
    L 0.2168,0.651 0.2085,0.647
    C 0.0878,0.582 0,0.478 0,0.361 0,0.164 0.2313,0 0.5048,0
    Z
</PathFigureCollection>
<PathGeometry x:Key="ShoeEdgeGeometry" Figures="{StaticResource ShoeEdgeFigures}" />

SOLUTION

In order to make the grid look as we expect we'll need to scale the geometry - this can be done by means of Geometry.Transform property. I think it is beneficial to define new geometry for that purpose. Then we only need to set ScaleTransform on the geometry with ScaleX and ScaleY equal to the width and height of the grid respectively. That's because the initial size of the geometry is 1x1. Here's the code:

<Grid Width="100" Height="200" (...)>
    <Grid.Resources>
        <PathGeometry x:Key="StaticClipGeometry" Figures="{StaticResource ShoeEdgeFigures}">
            <PathGeometry.Transform>
                <ScaleTransform ScaleX="100" ScaleY="200" />
            </PathGeometry.Transform>
        </PathGeometry>
    </Grid.Resources>
    <Grid.Clip>
        <StaticResource ResourceKey="StaticClipGeometry" />
    </Grid.Clip>
    (...)
 </Grid>

This however is somewhat limiting, because the size of the grid needs to be constant and known at compile-time.

To make the clip geometry adjust to the size of the grid dynamically we'll need to bind the Geometry.Transform property, and because we will bind to both Grid.ActualWidth and Grid.ActualHeight, we are going to need a simple converter:

public class SizeToScaleConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return new ScaleTransform
        {
            ScaleX = (double)values[0],
            ScaleY = (double)values[1],
        };
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Then we define the grid:

<Grid (...)>
    <Grid.Resources>
        <PathGeometry x:Key="DynamicClipGeometry" Figures="{StaticResource ShoeEdgeFigures}">
            <PathGeometry.Transform>
                <MultiBinding>
                    <MultiBinding.Converter>
                        <local:SizeToScaleConverter />
                    </MultiBinding.Converter>
                    <Binding RelativeSource="{RelativeSource AncestorType=Grid}"
                             Path="ActualWidth" />
                    <Binding RelativeSource="{RelativeSource AncestorType=Grid}"
                             Path="ActualHeight" />
                </MultiBinding>
            </PathGeometry.Transform>
        </PathGeometry>
    </Grid.Resources>
    <Grid.Clip>
        <StaticResource ResourceKey="DynamicClipGeometry" />
    </Grid.Clip>
    (...)
 </Grid>

And the end result looks like this:

这篇关于裁剪到WPF中的一个路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆