2

我正在尝试创建这样的控件:鱼骨

该控件表示4个瓷砖对象的状态完成(在上面的附图中,2已完成,2未完成)

为了实现这一点,我创建了一个水平方向的 ListView,并且我正在创建一个内部有一些边框的数据模板。不确定这是否是正确的方法或者是否可以使用更简单的方法,但是我面临的问题是下列的:在此处输入图像描述

  1. 我无法关闭最后一项的边框。这是因为我的列表视图的 itemsource 中有 4 个项目,并且每个项目都在左侧绘制了一个边框。问题是我如何专门为最后一项绘制右边框。

  2. 穿过中间的线实际上应该在灰色阴影后面......我该如何实现?

代码如下:

        <Style x:Key="FishBoneStyle" TargetType="{x:Type Border}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=Completed}" Value="True">
                    <Setter Property="Background" Value="DarkGray"/>
                    <Setter Property="Margin" Value="0,3,-2,3"/>
                </DataTrigger>              
            </Style.Triggers>
        </Style>

        <DataTemplate x:Key="FishBoneTemplate">
            <Grid Height="25">
            <Border BorderThickness="1,0,0,0" BorderBrush="Black" Height="25" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
                <Border Style="{StaticResource FishBoneStyle}" x:Name="FishBoneBorder" Width="25">
            </Border>
            </Grid>         
        </DataTemplate>

<!-- The Main Grid-->
<Grid Grid.Row="1" Height="30" Width="130" HorizontalAlignment="Left">
<ListView BorderThickness="0,0,0,0" BorderBrush="Black" ItemsSource="{Binding ProgressTiles}" ItemTemplate="{StaticResource FishBoneTemplate}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
  <StackPanel Orientation="Horizontal"></StackPanel>
 </ItemsPanelTemplate>
   </ListView.ItemsPanel>
</ListView>

<!-- The line which passess through the center-->
  <Border VerticalAlignment="Center" HorizontalAlignment="Left" Width="100" Margin="3,0,2,0" BorderBrush="Black" BorderThickness="1"></Border>
</Grid>

..这是位于我的视图模型中的可观察集合中的模型。总是有4个。

public class ProgressTile : INotifyPropertyChanged
    {
        private bool _completed;
        public bool Completed
        {
            get { return _completed; }
            set
            {
                _completed = value;
                InvokePropertyChanged("Completed");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        public void InvokePropertyChanged(string e)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(e));
        }
    }

请您建议如何获得与所附图片一致的外观。您还可以建议如何解决为最后一项绘制边框并将穿过中间的线发送到背景的问题吗?

4

1 回答 1

2

可以做得更简单:

<Window x:Class="So17362172FishBoneProgressBar.MainWindow" x:Name="root"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Fish Bone Progress Bar" Height="350" Width="525" SnapsToDevicePixels="True">
    <Grid Width="100" Height="20">
        <TickBar Fill="Gray" TickFrequency="25" Placement="Top"/>
        <TickBar Fill="Gray" TickFrequency="25" Placement="Bottom"/>
        <Line Stroke="Gray" X1="0" Y1="10" X2="100" Y2="10"/>
        <ItemsControl ItemsSource="{Binding Tiles, ElementName=root}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Rectangle x:Name="rect" Fill="Gray" VerticalAlignment="Center" Width="25" Height="10"/>
                    <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding Completed}" Value="False">
                            <Setter TargetName="rect" Property="Visibility" Value="Collapsed"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</Window>
  1. ListView是不必要的。简单得多ItemsControl就足够了。
  2. 刻度可以用 绘制TickBar。由于内部刻度被绘制得更小,两个刻度条彼此重叠(这不应该成为问题,因为它们非常轻量级)。
  3. 绘制顺序由逻辑树中的顺序决定。如果您希望将某些内容绘制在另一个之上,请将其放入较低的 XAML 中。
  4. Grid如果它只包含一个控件,则它是不必要的。
于 2013-06-28T11:14:42.340 回答