Deriving (Expanding) a Control Template in WPF - c#

I have this DataGrid I want to change the Disabled behaviour (xaml);
I want to change this small part in the template.
If it is not possible i dont mind to use:
<Setter Property="OverridesDefaultStyle" Value="True"/>
And To replace the entire xaml (template) of my control, But I need the complete template to copy paste and help where to change the Disabled look-like part.
Can anyone help me?

EDIT: It's been pointed out that all the default control templates are available at MSDN which makes the below relevant, but I'll leave it here for interest.
Given an instance of a control you get serialize the markup for the control template using the System.Windows.Markup.XamlWriter class.
To get a control template:
string markup = System.Windows.Markup.XamlWriter.Save(control.Template);
To get a complete dump (including triggers etc) of the control template use.
StringBuilder markupBuilder = new StringBuilder();
XmlWriter writer = XmlWriter.Create(markupBuilder);
System.Windows.Markup.XamlDesignerSerializationManager manager =
new System.Windows.Markup.XamlDesignerSerializationManager(writer);
manager.XamlWriterMode = System.Windows.Markup.XamlWriterMode.Value;
// data grid named dataGrid1
var template = dataGrid1.Template;
System.Windows.Markup.XamlWriter.Save(dataGrid1.Template, manager);
string markup = markupBuilder.ToString();
If you just looking to change the foreground color of the DataGrid when it's disabled, you should be able to use styles together with triggers rather than replacing the entire template.
<DataGrid>
<DataGrid.Resources>
<Style
TargetType="{x:Type DataGridColumnHeader}">
<Style.Triggers>
<DataTrigger
Binding="{Binding IsEnabled, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
Value="False">
<Setter
Property="Foreground"
Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style
TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<DataTrigger
Binding="{Binding IsEnabled, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
Value="False">
<Setter
Property="Foreground"
Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<!-- Column Definitions -->
</DataGrid>
Adding the above 2 styles to the DataGrid's resources collection will, set the foreground of each column header and data row cell to green when the DataGrid is disabled.

To define the disabled behavior of any control, you should change the Disabled visual state accordingly in the control template.

Related

WPF DataTrigger Based on Color

I'm trying to change the background of control A based on the background of control B, using a DataTrigger.
I've attempted to do this the conventional way you would change any property in a DataTrigger. Worst case I figure I can just use a converter, but wanted to try this first. Where have I gone astray, or is there simply no way to do this (i.e., bind to a control's background in a DataTrigger)?
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding Background, ElementName=Icon}" Value="Black">
<Setter Property="Background" Value="LimeGreen"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>

"Enter" key not leaving cell in RadGridView

All around my project I'm facing similar problem, which is "Enter" key, creating new line in cell, instead of move to next line.
My current telerik version is 2018.1.122.45, and default, expected behavior is to leave cell, after pressing "Enter" key (according to telerik documentation, and helpdesk).
However, in my case it always makes new line within cell being edited.
I'm using Visual Studio 2013 theme, my implementation of RadGridView is correct, I've pasted my RadGridView, to project, I got from telerik support, and there, Enter was working as expected. Also, they've pasted my RadGridView implementation to their project and it also worked correctly.
Have anyone faced similar problem? I'm looking for solution, since I can't track source of this issue (even with teleriks help).
I've found a solution to this problem, and other Styles problems. Implementing style in the way demonstrated in telerik documentation (f.e. https://docs.telerik.com/devtools/wpf/controls/radgridview/styles-and-templates/styling-a-row) has some issues not mentioned in documentation.
<Style TargetType="telerik:GridViewRow">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="White"/>
</Style>
This is one of the simpliest examples of implementing style. In my case it was:
<Style TargetType="telerik:GridViewCell"
x:Key="IloscNormalStyle"
BasedOn="{StaticResource GridViewCellStyle}">
<Setter Property="Background"
Value="#c3d8c7" />
<Setter Property="Foreground"
Value="Black" />
</Style>
And it works just fine. The biggest issue is that it completly ignores implemented Theme for project and all it's behaviours, which are, for example, selection behavior, enter key press, borders, etc. In order to tell style to not ignore implemented theme, I needed to insert this code to my styles:
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=telerik:GridViewRow}}"
Value="True">
<Setter Property="Background"
Value="{Binding Background}" />
</DataTrigger>
</Style.Triggers>
Which finally made my style works with desired behavior. Full style code:
<Style TargetType="telerik:GridViewCell"
x:Key="IloscNormalStyle"
BasedOn="{StaticResource GridViewCellStyle}">
<Setter Property="Background"
Value="#c3d8c7" />
<Setter Property="Foreground"
Value="Black" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=telerik:GridViewRow}}"
Value="True">
<Setter Property="Background"
Value="{Binding Background}" />
</DataTrigger>
</Style.Triggers>
</Style>
I think it is a major issue for telerik (or maybe even WPF), but this couple lines of code resolves most of problems with custom cell/row styling.

WPF Custom Control That Displays Content Inline or in a Popup

I am creating a custom WPF content control that has a DisplayMode property which can be:
Inline
Popup
When DisplayMode="Inline", my ControlTemplate can use a standard ContentPresenter like normal.
However, when DisplayMode="Popup", I want the Content to be displayed in a Popup control.
How should I solve this problem?
Does it have to happen purely in code when the DisplayMode property changes? How do I move the content of the Content property between a ContentPresenter and the Popup?
It looks like I was trying to make this more complex than it really is.
The solution to this was to create two separate ControlTemplate(s). One that displays inline and one that displays in a Popup control.
Next, all I had to do was create a couple style triggers that change the ControlTemplate based on the value of the DisplayMode property.
It looks like this:
<Style x:Key="MyControlStyle" TargetType="{x:Type my:MyControl}">
<Setter Property="Template" Value="{StaticResource InlineTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding DisplayMode}" Value="Inline">
<Setter Property="Template" Value="{StaticResource InlineTemplate}"/>
</DataTrigger>
<DataTrigger Binding="{Binding DisplayMode}" Value="Overlay">
<Setter Property="Template" Value="{StaticResource OverlayTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>

Set Background of button based on Content or CustomDP value

I have a button whose Content property keeps changing based on certain conditions which are set from the ViewModel. Essentially it gets set a value from 0 to 1000.
I also have another custom DP property on the same button whose value can be set to a certain enum.
What I am trying to solve is as follows (and unfortunately have no idea how I should go about it):
If my button content value is 0 - background of the button should be Gray.
If my button content value is 1 - background of the button should be Yellow.
If my button content value is 1 & the Custom DP has a value set (not the default value) - background should change to Red.
If my problem statement was just dealing with setting a background based on the integer set on the content - I could easily use Converters (String to Brush) and set my background. But the last condition which is now setting my background based on custom DP value coming in - have no idea how to solve...
Can somebody please suggest me an approach - sample code to solve such a problem.
<Button Content="0">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Content}" Value="0">
<Setter Property="Background" Value="Gray"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Content}" Value="1">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Content}" Value="1"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=YourDP}" Value="YourValue"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="Red"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
You can use multi-conditions triggers or multi data triggers. See this link and this link.

Using trigger to change property of many items

I created a WPF custom control, which works fine.
It has a style which sets some properties and a template.
Now i want to change the control, so it has a 'Active' property.
If this is true it should use the Property 'ActiveBrush' for the Stroke
of some Rectangles in the Template, else it should use 'InactiveBrush'.
I want to use the ActiveBrush as the default Stroke, and change it to InactiveBrush
with a Trigger.
This works fine with one Rectangle when i use this:
<Trigger Property="Active" Value="False">
<Setter TargetName="Rec1" Property="Stroke" Value="{Binding Path=InactiveBrush, RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
But since I don't want to set each rectangle with a seperated setter, I am asking myself if it shouldn't be possible to set the property of all Rectangles in the Template with one Setter.
I already tried:
<Trigger Property="Active" Value="False">
<Setter Property="Rectangle.Stroke" Value="{Binding Path=InactiveBrush, RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
But this didn't work.
Has anyone a suggestion, how to implement this?
Thanks in advance.
#Robert Rossney - this style will not run since a target type of Rectangle doesn't have a property Active. But that is the right path to go, with a minor change:
<Style TargetType="Rectangle">
<Style.Triggers>
<DataTrigger Binding="{Binding Active, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MyControl}}}" Value="False">
<Setter Property="Stroke" Value="{Binding Path=InactiveBrush, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MyControl}}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
This style should be nested in Style.Resources of the control style or in ControlTemplate.Resources of the ControlTemplate for the control. This way you're localizing this style only to your control. Any Rectangle outside of your control will not be affected.
I'm sure you know this but are just overlooking it: If you want to apply a style to all controls of a type, create a style with a TargetType of that type and put it in your custom control's resource dictionary. If you still need to apply specific styles to individual controls of that type, define those styles using the BasedOn property.
So, in your MyControl.Resources element, you'd put:
<Style TargetType="Rectangle">
<Style.Triggers>
<Trigger Property="Active" Value="False">
<Setter Property="Stroke" Value="{Binding Path=InactiveBrush, RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
<Style>
<Style>
and any Rectangle that needed its own style would start like this:
<Style TargetType="Rectangle" BasedOn="{StaticResource {x:Type Rectangle}}">

Categories