0

私の WPF アプリケーションでは、ComboBox を再テンプレート化しました。問題は、BorderThickness を適切に適用できないように見えることです。私はそれを正しくやっていると思いますが、結果が期待したものではないため、何かが欠けているに違いありません(常に厚さ1のままです)。

UserControl で使用される ComboBox (厚さが 3 であることに注意してください):

<ComboBox DockPanel.Dock="Top" SelectedItem="{Binding CurrentAnalysisKey}" 
          ItemsSource="{Binding AnalysisKeys}" Height="25"
          BorderBrush="{StaticResource ListBoxBorderBrush}"
          BorderThickness="3"
          DisplayMemberPath="ReaffectedName" Margin="0,5" />

リソース ファイルで定義されている ComboBox スタイル:

<Style TargetType="{x:Type ComboBox}">
  <Setter Property="Foreground"
          Value="White" />
  <Setter Property="SnapsToDevicePixels"
          Value="true" />
  <Setter Property="BorderBrush"
          Value="{StaticResource BlackBorderBrush}" />
  <Setter Property="BorderThickness"
          Value="2" />
  <Setter Property="Template"
          Value="{DynamicResource ComboBoxTemplate}" />
</Style>

<Style d:IsControlPart="True"
       TargetType="{x:Type ComboBoxItem}">
  <Setter Property="Foreground"
          Value="White" />
  <Setter Property="SnapsToDevicePixels"
          Value="true" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type ComboBoxItem}">
        <ControlTemplate.Resources>
          <Storyboard x:Key="HoverOn">

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="HoverRectangle"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
              <SplineDoubleKeyFrame KeyTime="00:00:00.1000000"
                                    Value="1" />
            </DoubleAnimationUsingKeyFrames>

          </Storyboard>
          <Storyboard x:Key="HoverOff">

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="HoverRectangle"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
              <SplineDoubleKeyFrame KeyTime="00:00:00.4000000"
                                    Value="0" />
            </DoubleAnimationUsingKeyFrames>

          </Storyboard>
          <Storyboard x:Key="SelectedOn">

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="SelectedRectangle"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
              <SplineDoubleKeyFrame KeyTime="00:00:00.1000000"
                                    Value="1" />
            </DoubleAnimationUsingKeyFrames>

          </Storyboard>
          <Storyboard x:Key="SelectedOff">

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                           Storyboard.TargetName="SelectedRectangle"
                                           Storyboard.TargetProperty="(UIElement.Opacity)">
              <SplineDoubleKeyFrame KeyTime="00:00:00.4000000"
                                    Value="0" />
            </DoubleAnimationUsingKeyFrames>

          </Storyboard>

        </ControlTemplate.Resources>
        <Grid SnapsToDevicePixels="true"
              Margin="1"
              IsHitTestVisible="True">
          <Rectangle x:Name="Background"
                     IsHitTestVisible="True"
                     Opacity="0.25"
                     Fill="{StaticResource NormalBrush}"
                     RadiusX="1"
                     RadiusY="1" />
          <Rectangle x:Name="HoverRectangle"
                     IsHitTestVisible="True"
                     Opacity="0"
                     Fill="{StaticResource NormalBrush}"
                     RadiusX="1"
                     RadiusY="1" />
          <Rectangle x:Name="SelectedRectangle"
                     IsHitTestVisible="False"
                     Opacity="0"
                     Fill="{StaticResource SelectedBackgroundBrush}"
                     RadiusX="1"
                     RadiusY="1" />
          <ContentPresenter Margin="5,2,0,2"
                            x:Name="contentPresenter"
                            VerticalAlignment="Center" />
          <Rectangle x:Name="FocusVisualElement"
                     Visibility="Collapsed"
                     Stroke="{StaticResource HoverShineBrush}"
                     StrokeThickness="1"
                     RadiusX="1"
                     RadiusY="1" />
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="IsHighlighted"
                   Value="true">
            <Trigger.ExitActions>
              <BeginStoryboard Storyboard="{StaticResource SelectedOff}"
                               x:Name="SelectedOff_BeginStoryboard" />
            </Trigger.ExitActions>
            <Trigger.EnterActions>
              <BeginStoryboard Storyboard="{StaticResource SelectedOn}"
                               x:Name="SelectedOn_BeginStoryboard" />
            </Trigger.EnterActions>

          </Trigger>
          <Trigger Property="IsMouseOver"
                   Value="True">
            <Trigger.ExitActions>
              <BeginStoryboard Storyboard="{StaticResource HoverOff}"
                               x:Name="HoverOff_BeginStoryboard" />
            </Trigger.ExitActions>
            <Trigger.EnterActions>
              <BeginStoryboard Storyboard="{StaticResource HoverOn}" />
            </Trigger.EnterActions>
          </Trigger>
          <Trigger Property="IsEnabled"
                   Value="false">
            <Setter Property="Foreground"
                    Value="{DynamicResource DisabledForegroundBrush}" />
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<Style x:Key="{x:Static ToolBar.ComboBoxStyleKey}"
       TargetType="{x:Type ComboBox}">
  <Setter Property="FontSize"
          Value="10" />
  <Setter Property="SnapsToDevicePixels"
          Value="true" />
  <Setter Property="Template"
          Value="{DynamicResource ComboBoxTemplate}" />
  <Setter Property="Foreground"
          Value="White" />
</Style>

ComboBox テンプレート: (ThicknessConverter を使用して、受信した Thickness をデバッグ ウィンドウに吐き出しました)

<ControlTemplate x:Key="ComboBoxTemplate"
                 TargetType="{x:Type ComboBox}">
  <Grid x:Name="grid">
    <Grid.Resources>
      <converters:ComboBoxThicknessConverter x:Key="thicknessConv" />
    </Grid.Resources>
    <ToggleButton Template="{DynamicResource ComboBoxToggleButton}"
                  BorderThickness="{TemplateBinding BorderThickness}"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  x:Name="ToggleButton"
                  Focusable="false"
                  IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                  ClickMode="Press" />
    <ContentPresenter HorizontalAlignment="Left"
                      x:Name="ContentSite"
                      Margin="{TemplateBinding BorderThickness, Converter={StaticResource thicknessConv}}"
                      VerticalAlignment="Center"
                      Content="{TemplateBinding SelectedItem}"
                      ContentTemplate="{TemplateBinding ItemTemplate}"
                      ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
                      IsHitTestVisible="False" />
    <Popup IsOpen="{TemplateBinding IsDropDownOpen}"
           Placement="Bottom"
           x:Name="Popup"
           Focusable="False"
           AllowsTransparency="True"
           PopupAnimation="Slide">
      <Grid MaxHeight="{TemplateBinding MaxDropDownHeight}"
            MinWidth="{TemplateBinding ActualWidth}"
            x:Name="DropDown"
            SnapsToDevicePixels="True">
        <Border x:Name="DropDownBorder"
                Background="{DynamicResource ControlBackgroundBrush}"
                CornerRadius="3" />
        <ScrollViewer Margin="4,6"
                      Style="{DynamicResource NuclearScrollViewer}"
                      SnapsToDevicePixels="True"
                      HorizontalScrollBarVisibility="Auto"
                      VerticalScrollBarVisibility="Auto"
                      CanContentScroll="True"
                      Foreground="{DynamicResource {x:Static SystemColors.ActiveCaptionTextBrushKey}}">
          <StackPanel IsItemsHost="True"
                      KeyboardNavigation.DirectionalNavigation="Contained" />
        </ScrollViewer>
      </Grid>
    </Popup>
  </Grid>
  <ControlTemplate.Triggers>
    <Trigger Property="HasItems"
             Value="false">
      <Setter Property="MinHeight"
              Value="95"
              TargetName="DropDownBorder" />
    </Trigger>
    <Trigger Property="IsEnabled"
             Value="false">
      <Setter Property="Foreground"
              Value="{DynamicResource DisabledForegroundBrush}" />
      <Setter Property="Opacity"
              TargetName="grid"
              Value="0.5" />
    </Trigger>
    <Trigger Property="IsGrouping"
             Value="true">
      <Setter Property="ScrollViewer.CanContentScroll"
              Value="false" />
    </Trigger>
    <Trigger Property="AllowsTransparency"
             SourceName="Popup"
             Value="true">
      <Setter Property="Margin"
              Value="0,2,0,0"
              TargetName="DropDownBorder" />
    </Trigger>
    <Trigger Property="local:Dragging.IsDragTarget"
             Value="True">
      <Setter Property="BorderBrush"
              Value="{StaticResource DragTargetBorderBrush}"
              TargetName="ToggleButton" />
    </Trigger>
  </ControlTemplate.Triggers>
</ControlTemplate>

ComboBoxToggleButton:

<ControlTemplate x:Key="ComboBoxToggleButton"
                 TargetType="{x:Type ToggleButton}">
  <Grid x:Name="grid">
    <Grid.Resources>
      <converters:SpecialThicknessConverter x:Key="cv2" />
    </Grid.Resources>
    <Grid.ColumnDefinitions>
      <ColumnDefinition />
      <ColumnDefinition Width="20" />
    </Grid.ColumnDefinitions>
    <Rectangle Grid.ColumnSpan="2"
               HorizontalAlignment="Stretch"
               x:Name="Rectangle"
               VerticalAlignment="Stretch"
               RadiusX="3"
               RadiusY="3"
               StrokeThickness="{TemplateBinding BorderThickness, Converter={StaticResource cv2}}"
               Fill="{DynamicResource LightBrush}"
               Stroke="{TemplateBinding BorderBrush}" />

    <Border Grid.Column="1"
            Margin="2"
            Background="{DynamicResource BorderBrush}"
            CornerRadius="3"
            x:Name="border" />
    <Border Grid.Column="1"
            Margin="2"
            Background="{DynamicResource HoverBrush}"
            CornerRadius="3"
            x:Name="HoverBorder"
            Opacity="0" />
    <Border Grid.Column="1"
            Margin="2"
            Background="{DynamicResource HoverShineBrush}"
            CornerRadius="3"
            x:Name="HoverShineBorder"
            Opacity="0" />
    <Path Grid.Column="1"
          HorizontalAlignment="Center"
          x:Name="Arrow"
          VerticalAlignment="Center"
          Fill="{x:Null}"
          Data="M0.5,0.5 L3,6.5 5.5,0.5"
          Stroke="{DynamicResource GlyphBrush}"
          Margin="5,0"
          Height="7"
          StrokeThickness="2"
          Stretch="Fill" />
    <Border Grid.Column="1"
            Margin="2"
            Background="{DynamicResource ShineBrush}"
            CornerRadius="3"
            x:Name="ShineBorder" />
  </Grid>
  <ControlTemplate.Triggers>
    <Trigger Property="IsMouseOver"
             Value="true">
      <Trigger.ExitActions>
        <BeginStoryboard Storyboard="{StaticResource HoverOff}"
                         x:Name="HoverOff_BeginStoryboard" />
      </Trigger.ExitActions>
      <Trigger.EnterActions>
        <BeginStoryboard Storyboard="{StaticResource HoverOn}" />
      </Trigger.EnterActions>
    </Trigger>
    <Trigger Property="IsChecked"
             Value="true" />
    <Trigger Property="IsEnabled"
             Value="False">
      <Setter Property="Foreground"
              Value="{DynamicResource DisabledForegroundBrush}" />
      <Setter Property="Stroke"
              TargetName="Arrow"
              Value="{DynamicResource DisabledForegroundBrush}" />
      <Setter Property="Background"
              TargetName="border"
              Value="{DynamicResource DisabledBorderBrush}" />
      <Setter Property="Opacity"
              TargetName="grid"
              Value="0.8" />
    </Trigger>
  </ControlTemplate.Triggers>
</ControlTemplate>

厚さコンバーターの 1 つを使用して、ComboBox の右側のボタンを構成する Borders と Path (20 ピクセル) 用のスペースを空けます。両方とも以下に含まれています。

public class ComboBoxThicknessConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var oldT = (Thickness)value;
        //Debug.WriteLine("cbx templ thickness = {" + oldT.Left + ", " + oldT.Top + ", " + oldT.Right + ", " + oldT.Bottom + "}");
        return new Thickness(oldT.Left, oldT.Top, oldT.Right + 20, oldT.Bottom);
    }

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

    #endregion
}


public class SpecialThicknessConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var oldT = (Thickness)value;
        Debug.WriteLine("toggle btn thickness = {" + oldT.Left + ", " + oldT.Top + ", " + oldT.Right + ", " + oldT.Bottom + "}");
        return oldT;
    }

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

    #endregion
}

ComboBoxToggleButton 内の StrokeThickness を手動でハードコーディングされた値に変更しない限り、常に同じ太さ 1 になります。

私が間違っているアイデアはありますか?私が理解している限り、階層のすべてのレベルに沿って ComboBox から BorderThickness を ComboBoxToggleButton の Rectangle に適切に渡しています。しかし、デバッグ ウィンドウを見ると、ComboBox の宣言時に使用される値ではなく、ComboBox スタイルのセッターで使用される値が表示されます。

前もって感謝します!

ショーン

4

2 に答える 2

1

TemplateBinding は、通常の Binding と同じではありません。特定の型の値を受け取り、それを同じ型のプロパティに直接渡すように最適化されています。Converters、StringFormat などの他のオプションは TemplateBinding では機能せず、迷惑なことにエラーは発生しません。変換を行う必要がある場合、または組み込みの型変換に依存して異なる型のプロパティを接続しようとしている場合は、代わりに RelativeSource TemplatedParent を使用して通常の Binding を使用する必要があります。

{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness, Converter={StaticResource cv2}}
于 2013-01-23T13:59:59.807 に答える
0

double結局のところ、問題はRectangle.Stroke(Shape.StrokeThicknessはa )とControl.BorderThickness(Thickness ... 4 doubles)のタイプの違いでした。

コンバーターを追加し、受け入れられた回答で提案されているようにTemplateBindingを使用し、それは機能しました。

StrokeThickness="{Binding BorderThickness, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource rect2DoubleConv}}"


public class RectangleToDoubleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var oldT = (Thickness)value;
        return (oldT.Left + oldT.Top + oldT.Right + oldT.Bottom) / 4.0;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
于 2013-01-24T10:31:27.213 に答える