【问题标题】:Custom Silverlight button with <Path> content and visual states具有 <Path> 内容和视觉状态的自定义 Silverlight 按钮
【发布时间】:2010-03-26 18:35:35
【问题描述】:

我想创建一个按钮控件,它的内容是 Path 元素——如果你愿意的话,是一个 IconButton。

此按钮应满足两个条件:

1. Path 元素的笔触和填充颜色应该可供 VisualStateManager 操作。

2。 Path 元素的数据字符串(定义它的形状)可以在代码或 XAML 中设置,这样我就可以创建多个这样的按钮,而无需为每个按钮创建新的自定义控件。

我能看到的唯一方法是不涉及任何 XAML。也就是说,在后面的代码中设置所有的视觉状态和动画,加上逐点生成Geometry对象(并且不能使用Path元素上方便的Data字符串属性)。

有没有更简单的方法来做到这一点?

编辑

所以我遇到的限制之一是 Silverlight 不支持 PathGeometry 中路径表达式的迷你语言,仅支持 Path.我在其中一些图标中有一些详细的几何图形,我真的不想使用 Illustrator 插件生成的方便字符串(很确定它是this one)并将它们分成单独的行段和曲线。

【问题讨论】:

    标签: silverlight-3.0 custom-controls user-controls


    【解决方案1】:

    不错的克里斯。如果你想将路径存储为资源,你可以像这样修改一些东西:

    首先将依赖属性改为Path类型:

    /// <summary>
    /// Button that contains an icon, where the icon is drawn from a path.  
    /// </summary>
    public class IconButton : Button
    {
        /// <summary>
        /// The path data that draws the icon. 
        /// </summary>
        public static readonly DependencyProperty IconPathProperty =
            DependencyProperty.Register("IconPath", typeof(Path), typeof(IconButton), new PropertyMetadata(default(Path)));
    
        /// <summary>
        /// Depencendy property backer. 
        /// </summary>
        public Path IconPath
        {
            get { return (Path)GetValue(IconPathProperty); }
            set { SetValue(IconPathProperty, value); }
        }
    
    }
    

    接下来,这里是 IconButton 控件模板。

    <!-- Icon Button Control Template -->
    <ControlTemplate x:Key="IconButtonControlTemplate" TargetType="{x:Type usercontrols:IconButton}">
        <Grid x:Name="Grid">
            <Border SnapsToDevicePixels="True"  x:Name="Border" CornerRadius="1" BorderThickness="1" BorderBrush="{StaticResource ButtonBorderBrush}">
                <Path x:Name="Icon" Height="16" Width="16" Stretch="Fill"                                  
                    Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IconPath.Data}" 
                        UseLayoutRounding="False" Grid.Column="1" VerticalAlignment="Center" Margin="0">
                    <Path.Fill>
                        <SolidColorBrush x:Name="IconColor" Color="{Binding Color, Source={StaticResource ButtonIconBrush}}" />
                    </Path.Fill>
                </Path>
            </Border>
        </Grid>
        <ControlTemplate.Triggers>
            <Trigger Property="IsKeyboardFocused" Value="true">
                <Setter Property="BorderBrush" Value="{StaticResource ButtonBorderBrush}" TargetName="Border"/>
            </Trigger>
            <Trigger Property="IsMouseOver" Value="true">
                <Setter Property="Background" Value="{StaticResource ButtonBackgroundMouseOverBrush}" TargetName="Border"/>
                <Setter Property="BorderBrush" Value="{StaticResource ButtonBorderMouseOverBrush}" TargetName="Border"/>
            </Trigger>
            <Trigger Property="IsPressed" Value="true">
                <Setter Property="Background" Value="{StaticResource ButtonBackgroundPressedBrush}" TargetName="Border"/>
            </Trigger>
            <Trigger Property="IsEnabled" Value="false">
                <Setter Property="Fill" Value="{StaticResource DisabledIconBrush}" TargetName="Icon"/>
                <Setter Property="Background" Value="{StaticResource ButtonBackgroundDisabledBrush}" TargetName="Border"/>
                <Setter Property="BorderBrush" Value="{StaticResource ButtonBorderDisabledBrush}" TargetName="Border"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>
    

    ...这是使用此模板的 IconButton 样式,并添加了一些默认值:

    <!-- Icon Button Style -->
    <Style TargetType="{x:Type usercontrols:IconButton}">
        <Setter Property="FocusVisualStyle" Value="{DynamicResource SimpleButtonFocusVisual}"/>
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="VerticalAlignment" Value="Top"/>
        <Setter Property="Height" Value="26"/>
        <Setter Property="Width" Value="26"/>
        <Setter Property="Margin" Value="5"/>
        <Setter Property="Content" Value="Button"/>
        <Setter Property="Template" Value="{StaticResource IconButtonControlTemplate}"/>
    </Style>
    

    现在您可以继续创建图标并将它们保存在您的资源文件中:

    <!-- Undo Icon -->
    <Path x:Key="UndoIcon" Stretch="Fill" Data="F1 M 87.7743,80.7396L 87.5215,75.9539L 89.8692,74.2202C 89.9775,75.0329 90.0859,76.586 90.0859,76.5318C 92.9302,73.7417 97.5369,72.9755 100.208,76.2158C 102.019,78.413 102.258,81.2543 99.7657,83.9361C 97.2735,86.6179 92.6142,90.1124 92.6142,90.1124L 90.3748,87.6744L 97.3096,81.769C 97.3096,81.769 99.1516,79.9992 97.8514,78.3558C 96.2374,76.316 94.384,77.2542 92.1447,78.8795C 92.1176,78.9608 93.3998,79.1143 94.3118,79.2768L 92.4336,81.4439L 87.7743,80.7396 Z "/>
    
    
    <!-- Filter Icon -->
    <Path x:Key="FilterIcon" Stretch="Fill" Data="F1 M 6,16L 10,16L 10.0208,10L 16,3L 16,2.86102e-006L 0,9.53674e-007L 0,3L 6,10L 6,16 Z "/>
    

    最后,创建按钮:

    <usercontrols:IconButton IconPath="{StaticResource UndoIcon}"></usercontrols:IconButton>
    

    【讨论】:

    【解决方案2】:

    Path Data 属性只是一个几何图形。当您说“几个这样的按钮”时,假设存在有限数量的此类按钮,这些按钮因图标而异。

    将每个“图标”作为 PathGeomerty 存储在 ResourceDictionary 中,并将该 ResourceDictionary 作为 app.xaml 中的合并字典引用。

    现在您可以简单地将几何图形分配给 Path shap Data 属性。

    【讨论】:

    • 我试图解决的主要问题是能够 1) 动态设置路径几何图形,同时 2) 允许 VisualStateManager 操作路径描边和填充颜色。
    【解决方案3】:

    对于上述问题的第二部分,这里有一个kludge,它非常适合将字符串路径数据存储为资源并从代码中访问它们。

    对于问题的第一部分,我只是在代码中创建了所有动画,将它们应用于鼠标事件,完全摆脱了 XAML 页面。

    【讨论】:

      【解决方案4】:

      这艘船可能早就航行了,但我需要一些非常相似的东西,并且能够通过从 Button 继承来滚动自己的东西:

       public class PathButton : Button
          {
              public static readonly DependencyProperty PathDataProperty =
                  DependencyProperty.Register("PathData", typeof(Geometry), typeof(PathButton), new PropertyMetadata(default(Geometry)));
      
              public Geometry PathData
              {
                  get { return (Geometry) GetValue(PathDataProperty); }
                  set { SetValue(PathDataProperty, value); }
              }
      
          }
      

                          <VisualStateManager.VisualStateGroups>
                              <VisualStateGroup x:Name="CommonStates">
                                  <VisualStateGroup.Transitions>
                                      <VisualTransition GeneratedDuration="0:0:0.1"/>
                                  </VisualStateGroup.Transitions>
                                  <VisualState x:Name="Normal"/>
                                  <VisualState x:Name="MouseOver">
                                      <Storyboard>                                    
                                          <ColorAnimation Duration="0" To="{StaticResource BlueColor}" Storyboard.TargetProperty="Color" Storyboard.TargetName="BackgroundRectangleColor" />
                                          <ColorAnimation Duration="0" To="{StaticResource WhiteColor}" Storyboard.TargetProperty="Color" Storyboard.TargetName="IconColor" />
                                      </Storyboard>
                                  </VisualState>
                                  <VisualState x:Name="Pressed"/>
                                  <VisualState x:Name="Disabled"/>
                              </VisualStateGroup>
                              <VisualStateGroup x:Name="FocusStates">
                                  <VisualState x:Name="Unfocused"/>
                                  <VisualState x:Name="Focused"/>
                              </VisualStateGroup>
                          </VisualStateManager.VisualStateGroups>
                          <Grid.Projection>
                              <PlaneProjection/>
                          </Grid.Projection>
                          <Rectangle x:Name="BackgroundRectangle" >
                              <Rectangle.Fill>
                                  <SolidColorBrush x:Name="BackgroundRectangleColor" Color="{StaticResource GrayColor}" />
                              </Rectangle.Fill>   
                          </Rectangle>
      
      
      
                          <Path x:Name="Icon" Stretch="Fill"                                  
                          Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=PathData}" 
                              UseLayoutRounding="False" Grid.Column="1" Width="24" Height="24" VerticalAlignment="Center" Margin="0">
                              <Path.Fill>
                                  <SolidColorBrush x:Name="IconColor" Color="{StaticResource LightGrayColor}" />
                              </Path.Fill>
                              </Path>
                          <TextBlock x:Name="Text" HorizontalAlignment="Center" TextWrapping="Wrap" Text="{TemplateBinding Content}" FontSize="9.333" FontFamily="Segoe UI Light" Foreground="{StaticResource LightGray}" Height="11" Margin="0,0,0,3" VerticalAlignment="Bottom"/>
      
                      </Grid>
                  </ControlTemplate>
              </Setter.Value>
          </Setter>
          </Style>
      

      示例用法:

      <Controls:PathButton Content="Options" PathData="F1M50.6954,32.1146C50.7057,31.1041,50.6068,30.1107,50.4583,29.1459L54.5052,25.9193C53.4636,22.0377,51.4583,18.5612,48.7409,15.7604L43.9063,17.5885C42.3776,16.3229,40.6407,15.3099,38.7552,14.5814L37.9857,9.47656C36.1237,8.98181 34.1719,8.68225 32.1511,8.66663 30.1302,8.65625 28.1771,8.92578 26.2995,9.39844L25.4714,14.4948C23.5794,15.2057,21.8229,16.1901,20.2813,17.4401L15.4675,15.5521C12.7201,18.3138,10.6706,21.7631,9.57556,25.6328L13.582,28.9088C13.4193,29.875 13.3164,30.8658 13.3047,31.8776 13.2969,32.8984 13.3945,33.8854 13.5469,34.8588L9.49353,38.0807C10.5417,41.9584,12.5469,45.4401,15.2604,48.2383L20.0938,46.4127C21.6224,47.6744,23.3659,48.6875,25.2513,49.4193L26.0091,54.5234C27.8802,55.0209 29.8333,55.3177 31.8503,55.3334 33.8698,55.3385 35.8243,55.0729 37.6979,54.6041L38.5352,49.5C40.4219,48.7916,42.1784,47.806,43.7253,46.5664L48.53,48.4531C51.2813,45.6836,53.3268,42.233,54.4245,38.3685L50.418,35.0963C50.5833,34.1224,50.6862,33.1354,50.6954,32.1146 M31.9362,41.6615C26.6068,41.6302 22.3073,37.2734 22.3411,31.9375 22.3776,26.6002 26.7266,22.3008 32.0651,22.3359 37.4011,22.3698 41.7005,26.7252 41.6653,32.0625 41.629,37.4023 37.2786,41.6979 31.9362,41.6615"
              Style="{StaticResource PathButtonStyle1}" Grid.RowSpan="2" Grid.Column="1" />
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-06
        • 2011-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-13
        相关资源
        最近更新 更多