C# WPF变量元素的数量

C# WPF变量元素的数量,c#,wpf,xaml,C#,Wpf,Xaml,我正在创建自己的滑块模板和样式。它与基本滑块类似,但轨迹栏包含具有适当间隔的圆(椭圆)。条中的圆数应确保滑块拇指正好停在圆上 在快速近似中,控件中应该有Slider.Maximum-Slider.Minimum/StepSize椭圆。但是,据我所知,没有办法从xaml中指定任意数量的变量,是吗 总之,这是代表我想要实现的目标的代码: <ControlTemplate x:Key="SliderHorizontal" TargetType="{x:Type Slider}">

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

在快速近似中,控件中应该有Slider.Maximum-Slider.Minimum/StepSize椭圆。但是,据我所知,没有办法从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继承的类并在那里添加椭圆吗?如果是这样的话,我能得到一个简单的例子吗?

一个
项目控件可以显示不同数量的内容。将其
ItemsSource
属性绑定到要显示的内容集合,并使用其
itemstemplate
属性确定它们的显示方式

这里是一个粗略的实现,您应该能够对其进行微调。特别是,
TickConverter
应该是
IMultiValueConverter
,具有
最小值
最大值
、和
TickFrequency
,通过
多绑定
,这样,当这些属性中的任何一个发生更改时,它都会自动重新调用

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();
    }
}
公共类TickConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
变量滑块=(滑块)值;
var tickOffsets=新列表();
var sliderRange=(slider.Maximum-slider.Minimum);
var tickcount=(int)Math.Floor(slideerrage/slider.TickFrequency);
返回可枚举的范围(0,tickcount);
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
抛出新的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>

一个
项目控件可以显示不同数量的内容。将其
ItemsSource
属性绑定到要显示的内容集合,并使用其
itemstemplate
属性确定它们的显示方式

这里是一个粗略的实现,您应该能够对其进行微调。特别是,
TickConverter
应该是
IMultiValueConverter
,具有
最小值
最大值
、和
TickFrequency
,通过
多绑定
,这样,当这些属性中的任何一个发生更改时,它都会自动重新调用

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();
    }
}
公共类TickConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
变量滑块=(滑块)值;
var tickOffsets=新列表();
var sliderRange=(slider.Maximum-slider.Minimum);
var tickcount=(int)Math.Floor(slideerrage/slider.TickFrequency);
返回可枚举的范围(0,tickcount);
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
抛出新的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>


这与您的问题没有直接关系,但是如果您是WPF新手,您应该查看一些关于使用MVVM模式的教程。通过这种方式使用WPF将非常容易,稍后您将感谢自己提前学习它。这与您的问题没有直接关系,但是如果您是WPF新手,您应该查看一些有关使用MVVM模式的教程。这样使用WPF将非常容易,稍后您将感谢自己提前学习它。在这种情况下,椭圆应该封装在滑块中,这是否意味着创建一个新的滑块?否则我不知道集合将被定义在哪里。你可以编写一个函数来返回一个浮点数集合。这真是太神奇了。我不知道ItemsControl可以做到这一点,uniformgrids确实是一个不错的选择。在这种情况下,椭圆应该封装在滑块中,这是否意味着要创建一个新的滑块?否则我不知道集合将被定义在哪里。你可以编写一个函数来返回一个浮点数集合。这真是太神奇了。我不知道ItemsControl可以做到这一点,uniformgrids确实是一个不错的选择