【问题标题】:WPF Slider with Custom Track using OpacityMask and CombinedGeometry使用 OpacityMask 和 CombinedGeometry 自定义轨道的 WPF 滑块
【发布时间】:2020-10-15 13:23:10
【问题描述】:

我想创建一个带有自定义轨道的 WPF 滑块,如下所示:

使用 OpacityMask 和 CombinedGeometry,我可以制作如下所示的滑块:

大红点被 OpacityMask 部分覆盖。有没有办法应用 OpacityMask 排除项,或操纵 ZIndex 以显示整个大红点?

这是 XAML:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style x:Key="WhisperSlider" TargetType="{x:Type Slider}">
            <Setter Property="Background" Value="Blue"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Slider}">
                        <ControlTemplate.Resources>
                            <Style TargetType="{x:Type RepeatButton}">
                                <Setter Property="OverridesDefaultStyle" Value="true"/>
                                <Setter Property="IsTabStop" Value="false"/>
                                <Setter Property="Focusable" Value="false"/>
                                <Setter Property="Template">
                                    <Setter.Value>
                                        <ControlTemplate TargetType="{x:Type RepeatButton}">
                                            <Border Background="{TemplateBinding Background}"/>
                                        </ControlTemplate>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                            <CombinedGeometry x:Key="TrackBar" GeometryCombineMode="Union">
                                <CombinedGeometry.Geometry1>
                                    <CombinedGeometry GeometryCombineMode="Union">
                                        <CombinedGeometry.Geometry1>
                                            <CombinedGeometry GeometryCombineMode="Union">
                                                <CombinedGeometry.Geometry1>
                                                    <EllipseGeometry Center="0 0" RadiusX="3" RadiusY="3" />
                                                </CombinedGeometry.Geometry1>
                                                <CombinedGeometry.Geometry2>
                                                    <EllipseGeometry Center="100 0" RadiusX="3" RadiusY="3" />
                                                </CombinedGeometry.Geometry2>
                                            </CombinedGeometry>
                                        </CombinedGeometry.Geometry1>
                                        <CombinedGeometry.Geometry2>
                                            <CombinedGeometry GeometryCombineMode="Union">
                                                <CombinedGeometry.Geometry1>
                                                    <EllipseGeometry Center="200 0" RadiusX="3" RadiusY="3" />
                                                </CombinedGeometry.Geometry1>
                                                <CombinedGeometry.Geometry2>
                                                    <EllipseGeometry Center="300 0" RadiusX="3" RadiusY="3" />
                                                </CombinedGeometry.Geometry2>
                                            </CombinedGeometry>
                                        </CombinedGeometry.Geometry2>
                                    </CombinedGeometry>
                                </CombinedGeometry.Geometry1>
                                <CombinedGeometry.Geometry2>
                                    <CombinedGeometry GeometryCombineMode="Union">
                                        <CombinedGeometry.Geometry1>
                                            <EllipseGeometry Center="400 0" RadiusX="3" RadiusY="3" />
                                        </CombinedGeometry.Geometry1>
                                        <CombinedGeometry.Geometry2>
                                            <RectangleGeometry Rect="0 -1 400 2" />
                                        </CombinedGeometry.Geometry2>
                                    </CombinedGeometry>
                                </CombinedGeometry.Geometry2>
                            </CombinedGeometry>
                        </ControlTemplate.Resources>
                        <Grid>
                            <Grid>
                                <Grid.OpacityMask>
                                    <DrawingBrush>
                                        <DrawingBrush.Drawing>
                                            <GeometryDrawing Brush="Black" Geometry="{StaticResource TrackBar}"/>
                                        </DrawingBrush.Drawing>
                                    </DrawingBrush>
                                </Grid.OpacityMask>
                                <Track Height="10" Name="PART_Track" Value="{TemplateBinding Value}">
                                    <Track.Thumb>
                                        <Thumb Background="{TemplateBinding Background}">
                                            <Thumb.Template>
                                                <ControlTemplate TargetType="{x:Type Thumb}">
                                                    <Ellipse Fill="Red" Width="16" Height="16" VerticalAlignment="Center"/>
                                                </ControlTemplate>
                                            </Thumb.Template>
                                        </Thumb>
                                    </Track.Thumb>
                                    <Track.DecreaseRepeatButton>
                                        <RepeatButton Background="{TemplateBinding Background}" Command="Slider.DecreaseLarge"/>
                                    </Track.DecreaseRepeatButton>
                                    <Track.IncreaseRepeatButton>
                                        <RepeatButton Background="Gray" Command="Slider.IncreaseLarge"/>
                                    </Track.IncreaseRepeatButton>
                                </Track>
                            </Grid>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <Slider Style="{StaticResource WhisperSlider}" VerticalAlignment="Center" 
                TickFrequency="1" Minimum="0" Maximum="4" Value="2" Margin="50,0,50,0"></Slider>
    </Grid>
</Window>

【问题讨论】:

标签: wpf xaml uwp wpf-controls uwp-xaml


【解决方案1】:

感谢zamoldar 的帮助,使用Adorner 解决了这个问题 - 一个附加到拇指的浮动几何体。

将此添加到 Slider XAML 的 Track.Thumb 部分:

<Track.Thumb>
    <Thumb Background="{TemplateBinding Background}">
        <Thumb.Template>
            <ControlTemplate TargetType="{x:Type Thumb}">
                <Ellipse x:Name="ThumbAdorner" Loaded="ThumbAdorner_Loaded" Fill="#0383DB" Width="16" Height="16" VerticalAlignment="Center"/>
            </ControlTemplate>
        </Thumb.Template>
    </Thumb>
</Track.Thumb>

在 Slider 的代码隐藏中:

    public partial class Slider : UserControl
    {
        public Slider()
        {
            InitializeComponent();
        }

        private void ThumbAdorner_Loaded(object sender, RoutedEventArgs e)
        {

            var ec = sender as Ellipse;
            var adorner = AdornerLayer.GetAdornerLayer(ec);
            adorner.Add(new EllipseAdorner(ec));
        }
    }

自定义装饰器的代码:

    public class EllipseAdorner : Adorner
    {
        public EllipseAdorner(UIElement adornedElement) : base(adornedElement)
        {
            MouseDown += EllipseAdorner_MouseDown;
        }

        private void EllipseAdorner_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            AdornedElement.RaiseEvent(e);
        }

        protected override void OnRender(DrawingContext drawingContext)
        {
            if (drawingContext != null)
            {
                var brush = ((Shape)AdornedElement).Fill;
                EllipseGeometry ellipseGeometry = new EllipseGeometry(new Point(8, 8), 8, 8);
                drawingContext.DrawGeometry(brush, null, ellipseGeometry);
            }
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    • 2014-04-01
    • 2012-07-26
    • 1970-01-01
    • 2011-01-05
    相关资源
    最近更新 更多