WPF变量ammount元素

时间:2017-09-01 14:28:39

标签: c# wpf xaml

我正在创建自己的滑块模板和样式。它类似于基本滑块,但轨迹栏包含具有适当分隔的圆(椭圆)。栏中的圆圈数应使滑块拇指正好停在它们上方。

在快速近似中,控件中应该有Slider.Maximum - Slider.Minimum / StepSize Ellipses。但是,据我所知,没有办法从xaml中指定可变数量的任何东西,是吗?

总之,这是代表我想要实现的目标的代码:

<ControlTemplate x:Key="SliderHorizontal" TargetType="{x:Type Slider}">
        <Grid Height="4">
            <Border x:Name="TrackBackground">
                <Rectangle x:Name="PART_SelectionRange" Fill="{StaticResource SliderThumb.Track.BackgroundSelected}" 
                           HorizontalAlignment="Left" Margin="0 0 16 0" Visibility="Hidden"/>
            </Border>
            <Grid>
                <!-- Have a variable ammount of column definitions and ellipses -->
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="4"/>
                    <ColumnDefinition Width="*"/>
                    ...
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="4"/>
                </Grid.ColumnDefinitions>
                <Ellipse Grid.Column="0" Fill="White"/>
                ...
                <Ellipse Grid.Column="X" Fill="White"/>
            </Grid>
            <Track x:Name="PART_Track">
                <Track.Thumb>
                    ...
                </Track.Thumb>
            </Track>
        </Grid>
        <ControlTemplate.Triggers>
            ...
        </ControlTemplate.Triggers>
    </ControlTemplate>

到目前为止,我的代码允许我使用固定的省略号,当它与滑块所代表的值不匹配时,它看起来非常糟糕。

我是WPF的新手,所以我不知道从代码隐藏中做这件事会带来什么。我可以简单地创建一个继承自Slider的类并在那里添加Ellipses吗?如果是这样,我可以得到一个简单的例子吗?

1 个答案:

答案 0 :(得分:3)

ItemsControl可以显示可变数量的内容。将其ItemsSource属性绑定到要显示的事物的集合,并使用其ItemTemplate属性来确定它们的显示方式。

这是一个粗略的实现,你应该能够微调。特别是,TickConverter应为IMultiValueConverterMinimumMaximumTickFrequency通过MultiBinding单独绑定 - 这样,它当任何属性发生变化时,将自动重新调用。

public class TickConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var slider = (Slider)value;

        var tickOffsets = new List<double>();

        var sliderRange = (slider.Maximum - slider.Minimum);

        var tickcount = (int)Math.Floor(sliderRange / slider.TickFrequency);

        return Enumerable.Range(0, tickcount);
    }

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

模板:

<ControlTemplate TargetType="{x:Type Slider}" x:Key="SliderHorizontal">
    <ControlTemplate.Resources>
        <local:TickConverter x:Key="TickConverter" />
    </ControlTemplate.Resources>
    <Grid Height="4">
        <Border x:Name="TrackBackground">
            <Rectangle 
                x:Name="PART_SelectionRange"
                HorizontalAlignment="Left" 
                Margin="0 0 16 0" 
                Visibility="Hidden"
                />
        </Border>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <ItemsControl
                Grid.Column="0"
                ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource TickConverter}}"
                >
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <!-- UniformGrid spaces items out evenly -->
                        <UniformGrid 
                            Rows="1" 
                            />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <!-- Align left to fill in start tick for each interval -->
                        <Ellipse
                            HorizontalAlignment="Left"
                            Fill="DeepSkyBlue"
                            Width="3"
                            Height="4"
                            />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
            <!-- And add the end tick -->
            <Ellipse
                Grid.Column="1"
                HorizontalAlignment="Left"
                Fill="DeepSkyBlue"
                Width="3"
                Height="4"
                />
        </Grid>
        <!-- 
        I don't know what you were doing with the thumb, but you didn't ask about it
        so I just ignored it. 
        -->
        <Track x:Name="PART_Track" />
    </Grid>
</ControlTemplate>