我想创建一个覆盖整个区域的控件,除了特定区域。该特定区域将呈椭圆/矩形形状。像下面的概念
我的想法是使用路径。下面是我的路径代码。
<Path Name="ShowcasePath" StrokeThickness="1" IsHitTestVisible="True">
<Path.Data>
<GeometryGroup>
<EllipseGeometry RadiusX="100" RadiusY="50"/>
<RectangleGeometry/>
</GeometryGroup>
</Path.Data>
</Path>
Centre
的{{1}}和EllipseGeometry
的{{1}}将在后面的代码中设置。
这种方法有两个问题
答案 0 :(得分:1)
我认为你已经非常接近你的例子,至少我发现它没有任何问题。如果您尝试以下代码,您将看到它完全符合您的描述:
<Grid>
<Button Content="Clickable" HorizontalAlignment="Left"
Margin="113,90,0,0" VerticalAlignment="Top" Width="75"/>
<Button Content="Non-Clickable" HorizontalAlignment="Left"
Margin="272,90,0,0" VerticalAlignment="Top" Width="75"/>
<Path Name="ShowcasePath" StrokeThickness="1" Fill="#88ff0000" IsHitTestVisible="True">
<Path.Data>
<GeometryGroup FillRule="EvenOdd">
<EllipseGeometry Center="150,100" RadiusX="100" RadiusY="50"/>
<RectangleGeometry Rect="0,0,500,500"/>
</GeometryGroup>
</Path.Data>
</Path>
</Grid>
请记住,用户仍然可以使用 Tab 更改焦点元素,并使用 Space 或 Return 激活元素,即使您将IsHitTestVisible
设为false
。
“将椭圆聚焦在元素上”功能可以很容易地解决这个问题:
public void FocusOnElement(FrameworkElement element)
{
Point center = new Point(element.ActualWidth / 2, element.ActualHeight / 2);
Point newPosition = element.TranslatePoint(center, ShowcasePath);
ellipseGeometry.Center = newPosition;
}
启用/禁用所有其他元素功能最好在viewmodel中处理,或者如果你没有,可以这样:
private void DiableAllButThisAndItsParents(FrameworkElement thisElement)
{
List<FrameworkElement> hierarchy = FindParents(thisElement).ToList();
foreach (FrameworkElement element in hierarchy)
{
element.IsEnabled = true;
if (ReferenceEquals(element, thisElement)) continue;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
var child = VisualTreeHelper.GetChild(element, i);
if (!(child is FrameworkElement childElement)) continue;
childElement.IsEnabled = hierarchy.Contains(childElement);
}
}
}
private IEnumerable<FrameworkElement> FindParents(FrameworkElement element)
{
DependencyObject current = element;
while (current != null)
{
if (current is FrameworkElement)
yield return (FrameworkElement) current;
current = VisualTreeHelper.GetParent(current);
}
}
把它们放在一起,看起来应该是这样的:
答案 1 :(得分:0)
而不是试图获得一个&#34; Click-through&#34;您可以简单地将元素(在您的情况下为togglebutton)带到前面(基本上是其他所有内容,以便它可以点击)。 您可以通过以下任一方式执行此操作:
YourElement.SetValue(Canvas.ZIndexProperty, index);
删除元素并将其再次添加到父网格(因此它基本上是要添加的最后一个元素)
parentGrid.Children.Remove(YourElement);
parentGrid.Children.Add(YourElement);
parentGrid.UpdateLayout();
用户成功与控件交互后,您可以将其切换回之前的状态。希望这有帮助..