Я создал контрольную панель для кнопок, и у меня возникла проблема - она не будет рисоваться или отображаться в конструкторе, но в процессе исполнения она выглядит просто отлично. В дизайнере область, в которой должен отображаться элемент управления, представляет собой только поле того же цвета, что и цвет фона.Кнопка с 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();
}
}
Как это выглядит в конструкторе:
Как это выглядит на Runtime:
Кнопки не наследуют свое свойство Foreground из родительского контейнера. Именно по этой причине я пытался привязать его к окну Ancester - это то, что, поскольку я единственный, кто использует эти шаблоны, я * * * гарантия всегда будет существовать. Я надеялся установить свой шаблон, чтобы мне никогда не пришлось вручную привязывать или изменять свойство Foreground кнопок, которые его реализуют. –
Да, да. Кнопка наследует свое свойство Foreground из Control, у которого Inherits установлено в true в своих метаданных. Окно также наследуется от Control, поэтому, если Foreground явно задано где-то, Button наследует свой Foreground из окна. –
Хм, я стою исправлено: я только что протестировал его, и кнопка действительно не наследует Foreground of the Window. Виноват... –