WPF为没有DataTemplate属性的控件创建DataTemplate

时间:2018-03-11 05:09:19

标签: wpf slider datatemplate

我正在为Slider创建自定义TickBar。这个CustomTickBar允许我在Slider上放置不同的标记。我将使用以下模型:

Interface IModel
{
   string Id;
}

Class Model1 : IModel
{
   string Id;
   string SomeProperty;
}

Class Model2 : IModel
{
   string Id;
   string SomeOtherProperty;
}

我的想法是为此TickBar控件提供List<IModel>,并根据标记图标将更改的IModel类型;例如对于Model1,它将是一个三角形,对于Model2,它将是一个矩形。我知道使用DataTemplate可以实现这一点。但是WPF TickBar没有DataTemplate属性。现在有一种方法可以使用DataTemplate属性和子类化TickBar吗?

注意:我知道我可以使用OnRender()创建自定义刻度,但是我试图通过编写尽可能少的代码来检查是否有办法。

3 个答案:

答案 0 :(得分:0)

TickBar没有默认样式,因此使用OnRender看起来就像他们设计它一样。

我想到的另一个解决方案是:

  1. 创建自定义控件,您拥有TickBar。也许继承自TickBar。
  2. 您可以为此自定义TickBar设置自己的样式,甚至可以基于您的某些模型数据。
  3. 使用themes/generic.xaml和此代码为您的控件应用自定义样式:

    static void MyCustomTickBar() {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomTickBar), new FrameworkPropertyMetadata(typeof(MyCustomTickBar)));
    }
    
    1. 编辑Slider的模板并使用新的TickBar,而不是内置于其中。
    2. Here是Slider的默认模板。我使用了样式窥探器来提取它。对不起,我无法在答案中提供,这太长了。

答案 1 :(得分:0)

首先尝试为滑块创建样式。 例如像这样:

<Window.Resources>
    <SolidColorBrush x:Key="HorizontalSliderTrackNormalBackground" Color="#FFE7EAEA"/>
    <LinearGradientBrush x:Key="HorizontalSliderTrackNormalBorder" EndPoint="0,1" StartPoint="0,0">
        <GradientStop Color="#FFAEB1AF" Offset="0.1"/>
        <GradientStop Color="#FFAEB1AF" Offset=".9"/>
    </LinearGradientBrush>
    <Style x:Key="SliderRepeatButtonStyle" 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}">
                    <Rectangle Fill="Transparent"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="CustomThumbForSlider" TargetType="{x:Type Thumb}">
        <Setter Property="OverridesDefaultStyle" Value="True"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Thumb}">
                    <Ellipse Fill="#009EFF" Stroke="#009EFF" Height="14" Width="14"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="MyCustomStyleForSlider" TargetType="{x:Type Slider}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Slider}">
                    <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="auto"/>
                                <RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <TickBar x:Name="TopTick" Visibility="Collapsed" Fill="{TemplateBinding Foreground}" Placement="Top" Height="10" Grid.Row="2"/>
                            <TickBar x:Name="BottomTick" Visibility="Collapsed" Fill="{TemplateBinding Foreground}" Placement="Bottom" Height="10" Grid.Row="2"/>
                            <Border x:Name="TrackBackground" 
                                    Background="{StaticResource HorizontalSliderTrackNormalBackground}"
                                    BorderBrush="{StaticResource HorizontalSliderTrackNormalBorder}"                                        
                                    BorderThickness="2" CornerRadius="1"
                                    Margin="5,0" VerticalAlignment="Center" Height="10.0" Grid.Row="1" >
                                <Canvas Margin="-6,-2">
                                    <Rectangle Visibility="Hidden" x:Name="PART_SelectionRange" Height="6.0"
                                               Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"
                                               Stroke="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}"
                                               StrokeThickness="2.0"/>
                                </Canvas>
                            </Border>
                            <Track x:Name="PART_Track" Grid.Row="1"  >
                                <Track.DecreaseRepeatButton>
                                    <RepeatButton  Style="{StaticResource  SliderRepeatButtonStyle}" Command="{x:Static Slider.DecreaseLarge}"/>
                                </Track.DecreaseRepeatButton>
                                <Track.IncreaseRepeatButton>
                                    <RepeatButton Style="{StaticResource SliderRepeatButtonStyle}" Command="{x:Static Slider.IncreaseLarge}"/>
                                </Track.IncreaseRepeatButton>
                                <Track.Thumb>
                                    <Thumb x:Name="Thumb" Style="{StaticResource CustomThumbForSlider}" Background="Black"/>
                                </Track.Thumb>
                            </Track>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

然后,您可以定义使用样式的滑块:

<Slider Name="CustomSlider" Style="{StaticResource MyCustomStyleForSlider}"/>

为了根据某些属性更改样式,您可以添加数据触发器。只需用新的样式替换现有样式:

<Style x:Key="CustomThumbForSlider" TargetType="{x:Type Thumb}">
    <Setter Property="OverridesDefaultStyle" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Thumb}">
                <Ellipse Fill="#009EFF" Stroke="#009EFF" Height="14" Width="14"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=IsDifferent}" Value="True">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Ellipse Fill="#009055" Stroke="#009055" Height="14" Width="14"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>

当滑块的datacontext对属性“IsDifferent”具有不同的值时,这个新Style将改变外观。

<Slider Name="CustomSlider" Style="{StaticResource MyCustomStyleForSlider}" DataContext="{Binding Path=MyContext}"/>

当然可以用你喜欢的不同形状替换绿色椭圆,也可以使用不同的属性。

对于模板问题,通常最好使用ControlTemplate或者另外一个ContentControl,其DataTemplate可以自由设置,并且它将作为您自己控件的父级。

答案 2 :(得分:-1)

我最近尝试用自己的定制滑块覆盖onrender,这很棘手。我不会走这条路。 我建议您考虑添加另一个控件来保持标记并使其与滑块的高度或宽度相匹配。 如果你的&#34;滴答&#34;在fixed,那可能只是一个包含路径的uniformgrid,你使用一个资源来使用DynamicResource几何定义它们的数据。您可以通过合并不同的几何图形来切换几何图形,也可以将其数据化。