WPF ControlTemplate: Como fornecer um valor padrão para a base de modelos?
-
22-09-2019 - |
Pergunta
Estou escrevendo um controle WPF que subclasse um botão. Eu então forneço um estilo padrão em temas genérico.xaml, que se parece com isso (simplificado):
<Style TargetType="{x:Type WPFControls:MyButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type WPFControls:MyButton}">
<Button
x:Name="PART_Button"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Gostaria que o usuário tivesse a oportunidade de alterar os antecedentes do controle, mas se ele não o fizer, gostaria de fornecer valor padrão. Como eu faço isso?
Quando faço isso como no código postado, o plano de fundo e o borderbrush são nulos (= inexistentes), a menos que o usuário os especifique explicitamente (que efetivamente força o usuário a sempre fornecer algum valor), mas os controles padrão do Windows (como botão) fornecem uma aparência padrão , isso ainda pode ser personalizado pelo usuário. Como fazer isso no meu controle?
Obrigada!
Solução de Michael Morton:
Você pode fornecer padrões como setters em estilo:
<Style TargetType="{x:Type TestTemplate:MyButton}">
<Setter Property="Background" Value="Red" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TestTemplate:MyButton}">
<Button
x:Name="PART_Button"
IsEnabled="{TemplateBinding IsEnabled}"
Content="{TemplateBinding Content}"
Background="{TemplateBinding Background}"
/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Uso:
<StackPanel>
<TestTemplate:MyButton Background="Blue">Explicitly blue</TestTemplate:MyButton>
<TestTemplate:MyButton>Naturally red</TestTemplate:MyButton>
</StackPanel>
Solução
Você pode apenas definir setters em seu estilo para as duas propriedades em questão.
Por exemplo, algumas definições gerais:
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#F3F3F3" Offset="0"/>
<GradientStop Color="#EBEBEB" Offset="0.5"/>
<GradientStop Color="#DDDDDD" Offset="0.5"/>
<GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
Então, na sua definição de estilo:
<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}" />
<Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}" />
Outras dicas
<Style TargetType="{x:Type WPFControls:MyButton}">
<Setter Property="Background" Value="Black">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type WPFControls:MyButton}">
<Button
x:Name="PART_Button"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Preste atenção na string seccond, eu defino a cor preta como o valor padrão em segundo plano.
Quando você declara uma propriedade de dependência para seus controles, você também declara o padrão como uipropertymetadata
Essa propriedade é o padrão de pincéis.red, como você pode ver na última linha.
public Brush MyBrush {
get { return (Brush)GetValue(MyBrushProperty); }
set { SetValue(MyBrushProperty, value); }
}
public static readonly DependencyProperty MyBrushProperty =
DependencyProperty.Register("MyBrush", typeof(Brush), typeof(MyQsFeature), new UIPropertyMetadata(Brushes.Red));
A outra maneira que você pode fazer é definir a cor padrão no construtor do seu controle personalizado, pois o construtor sempre é chamado antes que quaisquer propriedades sejam definidas pelo usuário se o usuário não defini -las, ele seria o seu padrão. Na verdade, eles sempre seriam definidos por você e, em seguida, qualquer configuração do usuário substituirá a sua. Isso é eficaz se você deseja definir as propriedades, como o fundo que você não está criando, as que vêm das suas classes base que você está herdando.
Também é possível "herdar" o estilo padrão do Button
Elemento criando instância de amostra e referenciando suas propriedades:
<Button x:Key="DefaultButton"/>
<Style TargetType="{x:Type TestTemplate:MyButton}">
<Setter Property="Background"
Value="{Binding Path=Background, Source={StaticResource DefaultButton}}" />
</Style>