I use a custom control from an external library, it has a property with ControlTemplate.
<Style x:Key="{x:Type controls:HeaderDiscountButton}" TargetType="{x:Type controls:HeaderDiscountButton}" BasedOn="{StaticResource {x:Type core:ValueButton}}">
<Setter Property="core:ButtonWithPopup.PopupTemplate">
<Setter.Value>
<ControlTemplate>
some complicated xaml code
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I would like to override it, but use old one in my new ControlTemplate, for example
<Style x:Key="{x:Type controls:HeaderDiscountButton}" TargetType="{x:Type controls:HeaderDiscountButton}" BasedOn="{StaticResource {x:Type core:ValueButton}}">
<Setter Property="core:ButtonWithPopup.PopupTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<Border>some complicated xaml code</Border>
<Border>some additional xaml code</Border>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I would like to avoid copying whole old code
This is not possible I am afraid. You can indeed base a Style on another Style and override specfic setters but you cannot "override" or inherit only a part of a ControlTemplate. Unfortunately you must (re)define the entire template as a whole.
So in this case you actually need to copy the (whole) original template and then edit it as per your requirements.
Related
I made a custom resource dictionary style for a TreeViewItem, but I am having difficulties with it.
<Style x:Key="StageTreeViewItem" TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
<Setter Property="Foreground" Value="Gold"/>
<Setter Property="FontFamily" Value="ArialN"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid>
<Image Name="PrimaryButtonImage" Source="pack://application:,,,/Images/TreeViewItem/TreeViewItem_Normal.png"/>
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The content/header of the TreeViewItem does not exist. I put "Stage One" as Header of the TreeViewItem, but it doesn't show up. Also, if I add multiple tree view items on another, it does not expand at all.
Another thing:
How can I remove the highlights when I select the tree view item? I want it to be transparent even when I hover over it and even when I click it. I don't want anything to happen, but I just don't know how, I tried everything.
Your provided code is not making it clear how you're setting header of TreeViewItem.
For other part of the question, you can use Triggers for events happening in WPF forms. Also have a look at this link, as you'll have to define a template for changing background color on mouse hover.
IsMouseOver Trigger not working in WPF
In our project we have a LookUp Base ViewModel which has a Required-Attribute on the SelectedItem property. I have another View that uses one of the child LookUps, which should ignore the Required-attribute. I've already overridden the IsValid method in the ViewModel, so saving without caring about the Required works correctly, but unfortunately it's still showing the validation error on the view when I empty the LookUp:
I had a couple of possibilities:
Split the LookUpBaseViewModel into two childs that are also "BaseViewModels", one with the RequiredAttribute and one without. This works, but it seems like a bit too much work and a lot of extra classes for just a single view that doesn't need to show the validation errors on the View.
Replace the RequiredAttribute with a RequiredIf-Attribute and add a boolean IsRequired parameter to the Constructor. This doesn't work since we use AutoFac in our project, so we can't use a boolean parameter for the ILookUpBaseViewModel-interface implementation.
Add a style to the LookUp-ContentControl in the View to hide the ValidationError border & text. This seemed like the easiest solution on paper, and it also makes sense to just hide the unwanted ValidationError border & text.
So, my question, how do I make the style to hide the default WPF validation error (so the red border and the text behind it)? I'm a novice when it comes to styles, but this is what I've tried (and which doesn't do anything it seems):
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="HideValidationErrorContentControlStyle" TargetType="{x:Type ContentControl}" BasedOn="{StaticResource {x:Type ContentControl}}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<!-- Empty -->
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<!-- Empty -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
With the style on my LookUp-ContentControl like this:
<ContentControl x:Name="MyLookup" Style="{StaticResource HideValidationErrorContentControlStyle}"/>
This is the result I want (even when a ValidationError would normally be shown):
Maybe it isn't your LookUp-ContentControl the one showing the error, but another control inside it. A TextBox, maybe?
Also, instead of leaving the ErrorTemplate empty, try to add an AdornedElementPlaceholder.
<Style x:Key="HideValidationErrorContentControlStyle" TargetType="{x:Type ContentControl}" BasedOn="{StaticResource {x:Type ContentControl}}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<AdornedElementPlaceholder />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
It's likely this isn't needed, but better be safe than sorry.
I've got a custom control in WPF, which has a variety of dependency properties that allow visual customization. For the sake of brevity I won't post the entire control, but it basically is setup like this:
<UserControl.Resources>
<Style TargetType="{x:Type MyControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MyControl}">
<Border BorderBrush="{TemplateBinding BorderColor}">
// more stuff here
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter>
</Setter>
</Style>
</UserControl.Resources>
The BorderColor property works fine if I set it directly, like this:
<ctl:MyControl BorderColor="Brushes.Red">....</ctl:MyControl>
But I want to set it application-wide. The problem I have is if I simply set the style with no key, it does not apply. Like this:
<Window.Resources>
<Style TargetType="{x:Type ctl:MyControl}">
<Setter Property="BorderColor" Value="Brushes.Red"/>
</Style>
</Window.Resources>
This does not do anything to the control. So I thought I'd just set a key and apply that style, like this:
<Style TargetType="{x:type ctl:MyControl}" x:Key="myStyle">....</Style>
<ctl:MyControl Style="{StaticResource myStyle}">.....</ctl:MyControl>
But this causes the control to vanish, I'm assuming because it's removing the Template. What am I doing wrong? With other framework controls you can just set the properties you want without losing the control template.
You need to inherit from the default style you have created.
inherit style from default style
I have a tab control with two different potential item templates:
<TabControl ItemTemplateSelector="{StaticResource tabTemplateSelector}"/>
Now, I also have styles for it:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
...
The thing is, I want the tab item style template to be different depending on the value of ItemTemplateSelector. How can I do this? Basically, I don't want that entire style rule to be applied to every tab item, just the ones with a specific tab item template.
Update: to make it clearer, the style has TargetType set to TabItem. I want to apply that style only to those tab items that have a specific item template.
The ContentPresenter in the ControlTemplate will display what's in the ItemTemplate. So you won't be able to switch the Template from inside the ControlTemplate.
Instead, you could use a DataTrigger to set the Template. The DataTrigger will check if the ItemTemplate that will be generated should have the other Template or not.
You will probably need a converter for this but here is an easy example. Say that your ItemTemplateSelector returns the other DataTemplate if Name is equal to "Tab 2". Then your Style with the DataTrigger would look like this
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<!-- Your first Template -->
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Name}" Value="Tab 2">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<!-- Your other Template -->
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
I have custom control that extends DataGrid. It is called ExtendedDataGrid. I want to provide style for ExtendedDataGrid that is the same as DataGrids style except it changes the template. I have tried something like this:
<Style TargetType="{x:Type MyControls:ExtendedDataGrid}" BasedOn="{StaticResource {x:Type DataGrid}}">
<Setter Property="Template">
...
</Setter>
</Style>
But it says that that the resource is not found.
So I try:
<Style TargetType="{x:Type MyControls:ExtendedDataGrid}" BasedOn="{StaticResource {ComponentResourceKey ResourceId=DataGridStyle, TypeInTargetAssembly={x:Type DataGrid}}}">
<Setter Property="Template">
...
</Setter>
</Style>
But it also does not work... So what do I do ?
Well mystery is solved :)
My first code above actually works:
<Style TargetType="{x:Type MyControls:ExtendedDataGrid}" BasedOn="{StaticResource {x:Type DataGrid}}">
<Setter Property="Template">
...
</Setter>
</Style>
I thought that it is not working becase VS (or Resharper) showed error in my code saying that resource is not found... Bug in VS (or Resharper) :(
If you create a style with a
TargetType property and base it on
another style that also defines a
TargetType property, the target type
of the derived style must be the same
as or be derived from the type of the
base style.
Your grid does inherit from DataGrid, right?