WPF's noteworthy IsHitTestVisible

WPF's noteworthy IsHitTestVisible

This property is set to false, which does not seem to have changed, but it has been completely ignored in operation. You can click directly on what is underneath it without triggering an event.

最后更新 10/20/2021 6:18 PM
普通的地球人
预计阅读 4 分钟
分类
WPF
标签
.NET WPF HitTest

We may not use this attribute very much, so let's first take a look at the explanation on MSDN:

The explanation was very professional, but I didn't understand it.

Let me tell you what I understand: setting this property to false may seem to have changed, but it has been completely ignored in operation. You can click directly on something underneath it without triggering an event.

This attribute can easily solve common troubles at work, such as the following example:

)

Pay attention to the top part. The effect is very simple, it's just a gradual change. But this gradient runs through both columns, making it a little troublesome to handle.

Of course, there are many solutions:

You can write two ListBoxItem styles. The first one is placed on a background with a gradient at the top, consistent with the right, and achieved through the style selector. This is obviously more troublesome.

You can also place a gradient on a large background and make the upper part of the ListBoxItem transparent. This is relatively simple, but may not achieve the desired effect.

The IsHitTestVisible attribute solves this problem well. Put a border directly on the upper layer, set the background to gradient, and set IsHitTestVisible to false. This way, you can not only see the gradient effect, but also click directly to ListBoxItem through the border. Setting a property solves the problem, which is very convenient. It's equivalent to putting a mask on it, but the mask can be seen but not touched.

Similarly, I also thought of a scene:

The top level of this effect is an image, with IsHitTestVisible = false and transparency = 0.3.

It's not like the picture is a background, and all controls are translucent.

See code:

XMAL:

<Grid>
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="70"></RowDefinition>
      <RowDefinition></RowDefinition>
      <RowDefinition Height="50"></RowDefinition>
    </Grid.RowDefinitions>
    <Border Background="#555F5F">
      <label Content="logo" Foreground="White"></label>
    </Border>
    <Grid Grid.Row="1" Background="#AAAFAF">
      <StackPanel
        HorizontalAlignment="Center"
        VerticalAlignment="Center"
        Button.Click="StackPanel_Click"
      >
        <button Width="132" Height="32" Content="金闪闪" Margin="10"></button>
        <button Width="132" Height="32" Content="小圆" Margin="10"></button>
      </StackPanel>
      <label
        Content="我不透明"
        Background="Green"
        Foreground="Blue"
        Width="100"
        Height="100"
        Margin="76,29,266,171"
      ></label>
      <label
        Content="我不透明"
        Background="Red"
        Foreground="Blue"
        Width="100"
        Height="40"
        Margin="112,40,230,220"
      ></label>
    </Grid>
    <Border Grid.Row="2" Background="#555F5F">
      <label Content="状态栏" Foreground="White"></label>
    </Border>
  </Grid>
  <image
    Name="img"
    HorizontalAlignment="Center"
    VerticalAlignment="Center"
    Width="0"
    Height="0"
    Source="/Image/jinshanshan.jpg"
    Stretch="Fill"
    Opacity="0.1"
    IsHitTestVisible="False"
  ></image>
</Grid>

Backstage:

private void StackPanel_Click(object sender, RoutedEventArgs e)
{
    Button btn = (Button)e.OriginalSource;
    string content = btn.Content.ToString();
    if (content == "金闪闪")
    {
        img.Source = new BitmapImage(new Uri(@"/Image/jinshanshan.jpg", UriKind.Relative));
    }
    if (content == "小圆")
    {
        img.Source = new BitmapImage(new Uri(@"/Image/xiaoyuan.jpg", UriKind.Relative));
    }

    DoubleAnimation daX = new DoubleAnimation();
    daX.From = 0;
    daX.To = 400;
    daX.FillBehavior = FillBehavior.HoldEnd;
    Storyboard.SetTarget(daX, img);
    Storyboard.SetTargetProperty(daX, new PropertyPath(Image.WidthProperty));
    DoubleAnimation daY = new DoubleAnimation();
    daY.From = 0;
    daY.To = 400;
    daY.FillBehavior = FillBehavior.HoldEnd;
    Storyboard.SetTarget(daY, img);
    Storyboard.SetTargetProperty(daY, new PropertyPath(Image.HeightProperty));
    DoubleAnimation daOp = new DoubleAnimation();
    daOp.From = 1;
    daOp.To = 0.3;
    daOp.FillBehavior = FillBehavior.HoldEnd;
    Storyboard.SetTarget(daOp, img);
    Storyboard.SetTargetProperty(daOp, new PropertyPath(Image.OpacityProperty));

    Storyboard sb = new Storyboard();
    sb.Children.Add(daX);
    sb.Children.Add(daY);
    sb.Children.Add(daOp);
    sb.Begin();
}
Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 9/13/2025

Migration from WPF to Avalonia series: Why I have to migrate WPF programs to Avalonia

In the past few years, our host computer software has been mainly developed using WPF and WinForm. These technologies are really easy to use on the Windows platform, and they have also accompanied us through the stage of small-scale trial production to today's large-scale delivery. However, with the development of business and changes in customer needs, the single Windows technology stack has gradually become a hurdle that we must overcome.

继续阅读
同分类 / 同标签 1/26/2025

WPF internationalizes with custom XML files

This article describes in detail the methods of using custom XML files to achieve internationalization in WPF programs, including installing the necessary NuGet package, dynamically obtaining language lists, dynamically switching languages, using translation strings in code and xaml interfaces, etc. It also provides source code links to help developers easily internationalize WPF applications.

继续阅读