2014-11-20 2 views
0

Я создал контрольную панель для кнопок, и у меня возникла проблема - она ​​не будет рисоваться или отображаться в конструкторе, но в процессе исполнения она выглядит просто отлично. В дизайнере область, в которой должен отображаться элемент управления, представляет собой только поле того же цвета, что и цвет фона.Кнопка с ControlTemplate не отображается в дизайнере

Что происходит и что мне нужно сделать, чтобы исправить это?

Мои ControlTemplate:

<ControlTemplate TargetType="Button" x:Key="TechButton"> 
    <ControlTemplate.Resources> 
     <TechControls:TagConverter x:Key="TagConverter"/> 
     <TechControls:OuterEdgeConverter x:Key="OuterEdgeConverter"/> 
     <TechControls:HighlightEdgeConverter x:Key="HighlightEdgeConverter" /> 
     <TechControls:ColorBrightness x:Key="ColorBrightnessConverter"/> 
     <TechControls:TagFontConverter x:Key="TagFontConverter"/> 
    </ControlTemplate.Resources> 
    <Border Name="RootElement"> 
     <Grid x:Name="theGrid" Background="{Binding Path=Background, RelativeSource={RelativeSource TemplatedParent}}"> 
      <Grid.Tag> 
       <MultiBinding Converter="{StaticResource TagConverter}"> 
        <Binding Path="ActualWidth" RelativeSource="{RelativeSource TemplatedParent}"></Binding> 
        <Binding Path="ActualHeight" RelativeSource="{RelativeSource TemplatedParent}"></Binding> 
       </MultiBinding> 
      </Grid.Tag> 

      <!--Outer Edge--> 
      <Polyline Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" Opacity="1" 
          Points="{Binding Path=Tag, ElementName=theGrid, Converter={StaticResource OuterEdgeConverter}, ConverterParameter=0 }"> 
      </Polyline> 
      <Polyline Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" Opacity="0.85" 
          Points="{Binding Path=Tag, ElementName=theGrid, Converter={StaticResource OuterEdgeConverter}, ConverterParameter=1 }"> 
      </Polyline> 
      <Polyline Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" Opacity="0.7" 
          Points="{Binding Path=Tag, ElementName=theGrid, Converter={StaticResource OuterEdgeConverter}, ConverterParameter=2 }"> 
      </Polyline> 
      <Polyline Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" Opacity="0.55" 
          Points="{Binding Path=Tag, ElementName=theGrid, Converter={StaticResource OuterEdgeConverter}, ConverterParameter=3 }"> 
      </Polyline> 
      <Polyline Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" Opacity="0.4" 
          Points="{Binding Path=Tag, ElementName=theGrid, Converter={StaticResource OuterEdgeConverter}, ConverterParameter=4 }"> 
      </Polyline> 
      <Polyline Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" Opacity="0.25" 
          Points="{Binding Path=Tag, ElementName=theGrid, Converter={StaticResource OuterEdgeConverter}, ConverterParameter=5 }"> 
      </Polyline> 

      <!--Bottom/Right Highlights--> 
      <Polyline Opacity="0.8" 
          Points="{Binding Path=Tag, ElementName=theGrid, Converter={StaticResource HighlightEdgeConverter}, ConverterParameter=0 }"> 
       <Polyline.Stroke> 
        <MultiBinding Converter="{StaticResource ColorBrightnessConverter}"> 
         <Binding Path="Foreground" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}"></Binding> 
         <Binding Source="0.4"></Binding> 
        </MultiBinding> 
       </Polyline.Stroke> 
      </Polyline> 
      <Polyline Opacity="0.4" 
          Points="{Binding Path=Tag, ElementName=theGrid, Converter={StaticResource HighlightEdgeConverter}, ConverterParameter=1 }"> 
       <Polyline.Stroke> 
        <MultiBinding Converter="{StaticResource ColorBrightnessConverter}"> 
         <Binding Path="Foreground" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}"></Binding> 
         <Binding Source="0.4"></Binding> 
        </MultiBinding> 
       </Polyline.Stroke> 
      </Polyline> 

      <!--MouseOver Highlights--> 
      <Polyline Opacity="0" x:Name="MouseOverHighlight" 
          Points="{Binding Path=Tag, ElementName=theGrid, Converter={StaticResource OuterEdgeConverter}, ConverterParameter=0 }"> 
       <Polyline.Fill> 
        <MultiBinding Converter="{StaticResource ColorBrightnessConverter}"> 
         <Binding Path="Foreground" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}"></Binding> 
         <Binding Source="0.5"></Binding> 
        </MultiBinding> 
       </Polyline.Fill> 
      </Polyline> 
      <Polyline Opacity="0" x:Name="MouseOverHighlightBorder1" 
          Points="{Binding Path=Tag, ElementName=theGrid, Converter={StaticResource HighlightEdgeConverter}, ConverterParameter=0 }"> 
       <Polyline.Stroke> 
        <MultiBinding Converter="{StaticResource ColorBrightnessConverter}"> 
         <Binding Path="Foreground" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}"></Binding> 
         <Binding Source="0.5"></Binding> 
        </MultiBinding> 
       </Polyline.Stroke> 
      </Polyline> 
      <Polyline Opacity="0" x:Name="MouseOverHighlightBorder2" 
          Points="{Binding Path=Tag, ElementName=theGrid, Converter={StaticResource HighlightEdgeConverter}, ConverterParameter=1 }"> 
       <Polyline.Stroke> 
        <MultiBinding Converter="{StaticResource ColorBrightnessConverter}"> 
         <Binding Path="Foreground" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}"></Binding> 
         <Binding Source="0.5"></Binding> 
        </MultiBinding> 
       </Polyline.Stroke> 
      </Polyline> 

      <!--Inner Shape--> 
      <Polyline Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" Opacity=".25" StrokeThickness="2" 
          Points="{Binding Path=Tag, ElementName=ContentPresenter}"> 
      </Polyline> 

      <ContentPresenter x:Name="ContentPresenter" Margin="26,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center"> 
       <ContentPresenter.Tag> 
        <MultiBinding Converter="{StaticResource TagFontConverter}"> 
         <Binding Path="ActualHeight" RelativeSource="{RelativeSource TemplatedParent}"></Binding> 
         <Binding Path="ActualWidth" RelativeSource="{RelativeSource TemplatedParent}"></Binding> 
         <Binding Source="0"></Binding> 
         <Binding Path="Content" RelativeSource="{RelativeSource TemplatedParent}"></Binding> 
         <Binding Path="FontFamily" RelativeSource="{RelativeSource TemplatedParent}"></Binding> 
         <Binding Path="FontStyle" RelativeSource="{RelativeSource TemplatedParent}"></Binding> 
         <Binding Path="FontWeight" RelativeSource="{RelativeSource TemplatedParent}"></Binding> 
         <Binding Path="FontStretch" RelativeSource="{RelativeSource TemplatedParent}"></Binding> 
         <Binding Path="FontSize" RelativeSource="{RelativeSource TemplatedParent}"></Binding> 
        </MultiBinding> 
       </ContentPresenter.Tag> 
       <TextBlock.Foreground> 
        <MultiBinding Converter="{StaticResource ColorBrightnessConverter}"> 
         <Binding Path="Foreground" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}"></Binding> 
         <Binding Source="0.4"></Binding> 
        </MultiBinding> 
       </TextBlock.Foreground> 
      </ContentPresenter> 
     </Grid> 
    </Border> 

    <ControlTemplate.Triggers> 
     <Trigger Property="Button.IsPressed" Value="True"> 
      <Setter TargetName="theGrid" Property="Margin" Value="1,1,-1,-1"/> 
     </Trigger> 
     <Trigger Property="Button.IsMouseOver" Value="True"> 
      <Setter TargetName="MouseOverHighlight" Property="Opacity" Value="0.3"/> 
      <Setter TargetName="MouseOverHighlightBorder1" Property="Opacity" Value="1"/> 
      <Setter TargetName="MouseOverHighlightBorder2" Property="Opacity" Value="0.6"/> 
      <Setter TargetName="ContentPresenter" Property="TextBlock.Foreground"> 
       <Setter.Value> 
        <MultiBinding Converter="{StaticResource ColorBrightnessConverter}"> 
         <Binding Path="Foreground" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}"></Binding> 
         <Binding Source="0.7"></Binding> 
        </MultiBinding> 
       </Setter.Value> 
      </Setter> 
     </Trigger> 
    </ControlTemplate.Triggers> 

</ControlTemplate> 

И соответствующие преобразовательные классы:

public class TagConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     Size sizeVal = new Size(double.Parse(values[0].ToString()), double.Parse(values[1].ToString())); 

     return sizeVal; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 
public class TagFontConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     PointCollection r = new PointCollection(); 

     double ActualHeight = double.Parse(values[0].ToString()); 
     double ActualWidth = double.Parse(values[1].ToString()); 
     double Offset = double.Parse(values[2].ToString()); 

     FormattedText ft = new FormattedText(values[3].ToString(), System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, 
      new Typeface((FontFamily)values[4], (FontStyle)values[5], (FontWeight)values[6], (FontStretch)values[7]), 
      (double)values[8], Brushes.Black); 

     double Height = ActualHeight - 14; 
     double Width = ft.Width + 14; 
     if (Width < ActualWidth/2) 
      Width = ActualWidth/2; 

     int startX = 22; 
     int startY = 7; 

     r.Add(new Point(startX + Offset, startY + Offset)); 
     r.Add(new Point(startX + Width - Offset, startY + Offset)); 
     r.Add(new Point(startX + Width - Offset, startY + (Height/2) - Offset)); 
     r.Add(new Point(startX + Width - (Height/2) - Offset, startY + Height - Offset)); 
     r.Add(new Point(startX + Offset, startY + Height - Offset)); 
     r.Add(new Point(startX + Offset, startY + Offset)); 

     return r; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 
public class OuterEdgeConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     Size desiredSize = (Size)value; 
     double ActualHeight = desiredSize.Height; 
     double ActualWidth = desiredSize.Width; 
     double DiagonalOffset = 10; 
     double BaseOffset = 1; 
     double AdditionalOffset = double.Parse(parameter.ToString()); 

     double Offset = BaseOffset + AdditionalOffset; 

     PointCollection r = new PointCollection(); 

     r.Add(new Point(0 + Offset, ActualHeight - Offset)); 
     r.Add(new Point(0 + Offset, DiagonalOffset)); 
     r.Add(new Point(DiagonalOffset, 0 + Offset)); 
     r.Add(new Point(ActualWidth - Offset, 0 + Offset)); 
     r.Add(new Point(ActualWidth - 0.5 - Offset, ActualHeight - DiagonalOffset)); 
     r.Add(new Point(ActualWidth - DiagonalOffset, ActualHeight - 0.5 - Offset)); 
     r.Add(new Point(0 + Offset, ActualHeight - 0.5 - Offset)); 

     return r; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 
public class HighlightEdgeConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     Size desiredSize = (Size)value; 
     double ActualHeight = desiredSize.Height; 
     double ActualWidth = desiredSize.Width; 
     double DiagonalOffset = 10; 
     double BaseOffset = 1; 
     double AdditionalOffset = double.Parse(parameter.ToString()); 

     double Offset = BaseOffset + AdditionalOffset; 

     PointCollection r = new PointCollection(); 

     r.Add(new Point(ActualWidth - Offset, 0 + Offset)); 
     r.Add(new Point(ActualWidth - 0.5 - Offset, ActualHeight - DiagonalOffset)); 
     r.Add(new Point(ActualWidth - DiagonalOffset, ActualHeight - 0.5 - Offset)); 
     r.Add(new Point(0 + Offset, ActualHeight - 0.5 - Offset)); 

     return r; 
    } 

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

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     Color color = (Color)ColorConverter.ConvertFromString(values[0].ToString()); 
     float correctionFactor = float.Parse(values[1].ToString()); 

     float red = (float)color.R; 
     float green = (float)color.G; 
     float blue = (float)color.B; 

     if (correctionFactor < 0) 
     { 
      correctionFactor = 1 + correctionFactor; 
      red *= correctionFactor; 
      green *= correctionFactor; 
      blue *= correctionFactor; 
     } 
     else 
     { 
      red = (255 - red) * correctionFactor + red; 
      green = (255 - green) * correctionFactor + green; 
      blue = (255 - blue) * correctionFactor + blue; 
     } 

     Color r = Color.FromArgb(color.A, (byte)red, (byte)green, (byte)blue); 

     return new SolidColorBrush(r); 
    } 

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

Как это выглядит в конструкторе:

enter image description here

Как это выглядит на Runtime:

enter image description here

ответ

0

После завинчивания вокруг с этим, я был в состоянии определить, что этот вопрос находится здесь:

Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}" 

Оказывается, что FindAncestor не рассосется в конструкторе, в результате инсульта является нулевым для всех моего рисунка.

0

Вы не должны привязываться к окну предка, так как он не гарантированно существует. Особенно в дизайнере. Вы делаете шаблон управления для кнопки, так что вы должны связываться с переднего плана кнопки, которая унаследует от окна или любой другой контейнер, он находится в Попробуйте это:.

Stroke="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}" 

или

Stroke="{TemplateBinding Foreground}" 
+0

Кнопки не наследуют свое свойство Foreground из родительского контейнера. Именно по этой причине я пытался привязать его к окну Ancester - это то, что, поскольку я единственный, кто использует эти шаблоны, я * * * гарантия всегда будет существовать. Я надеялся установить свой шаблон, чтобы мне никогда не пришлось вручную привязывать или изменять свойство Foreground кнопок, которые его реализуют. –

+0

Да, да. Кнопка наследует свое свойство Foreground из Control, у которого Inherits установлено в true в своих метаданных. Окно также наследуется от Control, поэтому, если Foreground явно задано где-то, Button наследует свой Foreground из окна. –

+0

Хм, я стою исправлено: я только что протестировал его, и кнопка действительно не наследует Foreground of the Window. Виноват... –

Смежные вопросы