WPF DataGrid*Column: set EditingElementStyle - wpf

I'm trying to modify the default style of DataGrid*Column. But it seems that the style is not used by DataGrid.
<Style x:Key="DataGridTextColumn_EditStyle" TargetType="{x:Type TextBox}" >
<Setter Property="SelectionBrush" Value="Red" />
</Style>
<Style TargetType="{x:Type DataGridTextColumn}">
<Setter Property="EditingElementStyle" Value="{StaticResource DataGridTextColumn_EditStyle}" />
</Style>
This way it shouldn't be necessary to set the style in DataGrid.Columns.

It's not possible to define default Style for DataGridTextColumn because DataGridTextColumn class is not FrameworkElement so it doesn't have Style property.

Related

Bind to default property value of another control style definition in xaml

I have a CustomControl and want to have the default value of TextBox default style definition. I don't know if it that is even possible.
This is what I have tried so far without success. But here you can see what I have in mind.
My default implementation to change the default style of the TextBox (in for example app.xaml to apply it global)
<Style TargetType="TextBox">
<Setter Property="BorderThickness" Value="2"/>
</Style>
Here I want to get the value of '2'.
<Style TargetType="controls:CustomControl">
<Setter Property="BorderThickness" Value="{Binding Source={x:Static TextBox.BorderThicknessProperty}}"/>
</Style>
The default value of the BorderThickness property of a TextBox is defined in the default style of the TextBox which is eventually applied to an instance of a TextBox at runtime.
So you cannot do something like this:
<Style TargetType="controls:CustomControl">
<Setter Property="BorderThickness" Value="{Binding Source={x:Static TextBox.BorderThicknessProperty}}"/>
</Style>
...unless you bind to an actual instance of a TextBox that uses the default style.
You could look at the default template of the TextBox and simply copy its default BorderThickness property value of 1 though:
<Style TargetType="controls:CustomControl">
<Setter Property="BorderThickness" Value="1"/>
</Style>
Obviously you can also bind to a property of a class from more than one Style, e.g.:
<Style TargetType="controls:CustomControl">
<Setter Property="BorderThickness" Value="{Binding Thickness, Source={StaticResource settings}}"/>
</Style>

MahApps setting style based on existing style has strange output

I copyied MahApps DataGrid's source code and It works fine if I change directly on the style such as setting HorizontalAlignment from left to right. But if I did
<Style BasedOn="{StaticResource MetroDataGridColumnHeader}" TargetType="{x:Type DataGridColumnHeader}"
x:Key="MetroDataGridColumnHeader1">
<Setter Property="HorizontalAlignment" Value="Right"></Setter>
</Style>
and replace the MetroDataGridColumnHeader with the new MetroDataGridColumnHeader1 inside DataGrid style, It gives strange output. Metro effects disappears.Any ideas?
You should set the HorizontalContentAlignment not the HorizontalAlignment.
<Style BasedOn="{StaticResource MetroDataGridColumnHeader}"
TargetType="{x:Type DataGridColumnHeader}"
x:Key="RightAlignmentMetroDataGridColumnHeader">
<Setter Property="HorizontalContentAlignment"
Value="Right" />
</Style>
Hope this helps.

How do I specify common layout markup or rules for controls in XAML?

I'm a WCF newbie, and I wonder, is it possible to declare in XAML that all my TextBoxes should have a height of 26, for example? That is, not to set the height of each item individually?
You need to define a style for your textbox
This will style the textbox when required
<Style x:Key="myTextBoxStyle">
<Setter Property="Height" Value="26" />
</Style>
<TextBox Text="Hi" Style="{StaticResource myTextBoxStyle}"/>
This will style all the textboxes
<Style TargetType="{x:Type TextBox}">
<Setter Property="Height" Value="26" />
</Style>
Put your Style into your resources block

Apply default WPF style

I have a global style that sets all my TextBox styles, but in some cases I want to revert just the Foreground color to the original non-custom-style color. I tried using {TemplateBinding Foreground} inside the specific TextBoxes that I wanted to revert. It didn't end up being valid XAML and I'm not sure that's the right way anyhow.
Any ideas? Thanks.
There's a few ways this could be done. If you look at the Precedence List on the MSDN
then you can see that the Forground set in ways 1-8 will override the Foreground from a default style. The easiest way being just to set the local value in the TextBox.
<TextBox Foreground="Red" />
Another thing that you can do is use the 'BasedOn' property of styles to override the other versions. This does require giving a key value to your default style, but that can then be used to also apply the default like in this example:
<Style TargetType="{x:Type TextBox}"
x:Key="myTextBoxStyle">
<Setter Property="Foreground"
Value="Red" />
<Setter Property="FontWeight"
Value="Bold" />
</Style>
<!-- Style applies to all TextBoxes -->
<Style TargetType="{x:Type TextBox}"
BasedOn="{StaticResource myTextBoxStyle}" />
<TextBox Text="Hello">
<TextBox.Style>
<Style BasedOn="{StaticResource myTextBoxStyle}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground"
Value="Blue" />
</Style>
</TextBox.Style>
</TextBox>
Edit:
In the case that the default style is applying a value and you want to revert it to the base value there are a few ways I can think of, off hand, to get this behavior. You can't, that I know of, bind back to the default theme value in a generic manner.
We can however do some other things. If we need the style to not apply some properties, we can set the style to {x:Null}, thus stopping the default style from applying. Or we can give the element it's own style that does not inherit from the base style and then re-apply only the setters that we need:
<TextBox Text="Hello" Style="{x:Null}" />
<TextBox Text="Hello">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="FontWeight"
Value="Bold" />
</Style>
</TextBox.Style>
</TextBox>
We could modify the default style so that the Foreground will only be set on certain conditions, such as the Tag being a certain value.
<Style TargetType="{x:Type TextBox}"
x:Key="myTextBoxStyle">
<Setter Property="FontWeight"
Value="Bold" />
<Style.Triggers>
<Trigger Property="Tag"
Value="ApplyForeground">
<Setter Property="Foreground"
Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
<TextBox Text="Hello" />
<TextBox Text="Hello" Tag="ApplyForeground" />

Can you define multiple TargetTypes for one XAML style?

In HTML/CSS you can define a style which can be applied to many types of elements, e.g.:
.highlight {
color:red;
}
can be applied to both P and DIV, e.g.:
<p class="highlight">this will be highlighted</p>
<div class="highlight">this will also be highlighted</div>
but in XAML you seem to have to define the TargetType for styles, otherwise you get an error:
<Style x:Key="formRowLabel" TargetType="TextBlock">
is there a way to allow a XAML style to be applied to multiple elements or even to leave it open as in CSS?
The setters in WPF styles are checked during compile time; CSS styles are applied dynamically.
You have to specify a type so that WPF can resolve the properties in the setters to the dependency properties of that type.
You can set the target type to base classes that contain the properties you want and then apply that style to derived classes. For example, you could create a style for Control objects and then apply it to multiple types of controls (Button, TextBox, CheckBox, etc)
<Style x:Key="Highlight" TargetType="{x:Type Control}">
<Setter Property="Foreground" Value="Red"/>
</Style>
...
<Button Style="{StaticResource Highlight}" Content="Test"/>
<TextBox Style="{StaticResource Highlight}" Text="Test"/>
<CheckBox Style="{StaticResource Highlight}" Content="Test"/>
<!-- Header text style -->
<Style x:Key="headerTextStyle">
<Setter Property="Label.VerticalAlignment" Value="Center"></Setter>
<Setter Property="Label.FontFamily" Value="Trebuchet MS"></Setter>
<Setter Property="Label.FontWeight" Value="Bold"></Setter>
<Setter Property="Label.FontSize" Value="18"></Setter>
<Setter Property="Label.Foreground" Value="#0066cc"></Setter>
</Style>
<!-- Label style -->
<Style x:Key="labelStyle" TargetType="{x:Type Label}">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Margin" Value="0,0,0,5" />
</Style>
I think both of these methods of declaring a style might answer your question.
In the first one, there is no TargetType specified, but the property names are prefixed with 'Label'. In the second one, the style is created for Label objects.
Another method to do it is:
<UserControl.Resources>
<Style x:Key="commonStyle" TargetType="Control">
<Setter Property="FontSize" Value="24"/>
</Style>
<Style BasedOn="{StaticResource commonStyle}" TargetType="ListBox"/>
<Style BasedOn="{StaticResource commonStyle}" TargetType="ComboBox"/>
</UserControl.Resources>
I wanted to apply a style to a Textblock and a TextBox but the selected answer didn't work for me because Textblock doesn't inherit from Control, in my case I wanted to affect the Visibility property, so I used FrameworkElement
<Style x:Key="ShowIfRequiredStyle" TargetType="{x:Type FrameworkElement}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ShowIfRequiredStyle, UpdateSourceTrigger=PropertyChanged}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<TextBlock Style="{StaticResource ResourceKey=ShowIfRequiredStyle}"/>
<TextBox Style="{StaticResource ResourceKey=ShowIfRequiredStyle}"/>
This works for the Visibility property because both items inherit from Frameworkelement and the property is defined there. Of course this will not work for properties defined only in Control, you can search the hierarchy tree and try to find a base class, anyway I thought this could help someone since this is a top search result and the selected answer is a little incomplete.
There is an alternative answer to the question. You CAN leave the TargetType parameter off the style altogether which will allow it to apply to various different controls, but only if you prefix the property name with "Control."
<Style x:Key="Highlight">
<Setter Property="Control.Foreground" Value="Red"/>
</Style>
Obviously, this only works for properties of the base control class. If you tried to set ItemsSource say, it would fail because there is no Control.ItemsSource
I got this working
<Style x:Key="HeaderStyleThin" TargetType="{x:Type Border}">
<Setter Property="Background" Value="Black" />
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background=" Value="Red" />
</Style>
</Style.Resources>
</Style>

Resources