Button width is not stretch - wpf

I try to use the metro style from MahApps but buttons becomes not "SizeToContent" or becomes not AutoResized or something like that.
This is my button style
<Style x:Key="GrayMetroButtonStyle" TargetType="Button" BasedOn="{StaticResource LightMetroWindowButtonStyle}">
<Setter Property="Margin" Value="5"/>
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Padding" Value="2"/>
</Style>
This is the style using in WPF. The width of the button's column is larger than the button needed to check autoresize.
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="80" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding ManifestFileName}" Margin="5" />
<Button Grid.Column="1" Content="Change" Margin="2" Visibility="{Binding LoadButtonVisibility}" Command="{Binding LoadManifest}" Style="{StaticResource GrayMetroButtonStyle}" />
</Grid>
And result is
As you see, content is out of the buttons width range.
If i clear the style refference, button get a properly behavior.
Which property are rule this behavior? How can i make this buttons autoresizable?
Thanks for replies.

According to the comments in the MahApps sources, LightMetroWindowButtonStyle is intended for the minimize, maximize, and close buttons in the title bar of a Metro-style window. For that reason, the style sets a fixed Width of 34.
It looks like the 'standard' button style for MahApps is MahApps.Metro.Styles.MetroButton, so I would suggest using that instead. It actually looks like this is the style that gets applied by default, as the second image you posted (the button with the style cleared) looks like it has this style already applied.
There are others too, like SquareButtonStyle and AccentedSquareButtonStyle, which are showcased in the MahApps example app:
If you want the 'flat' look, MetroFlatButton looks pretty similar to the button in the first image. You can see the various MahApps button styles in the MahApps docs and see the actual source code on GitHub .
Note that some of the button styles force their content to display in lowercase. If you want to avoid this, you can extend one of the MahApps styles and override a single property, e.g.:
<Style x:Key="SquareButtonStyleNormalCase"
BasedOn="{StaticResource SquareButtonStyle}"
TargetType="Button">
<Setter Property="m:ControlsHelper.ContentCharacterCasing"
Value="Normal" />
</Style>

Related

WPF fixing fuzzy DataPicker text boxes that have drop shadows

I have a WPF form that has TextBoxes and DatePickers. The DatePicker text boxes fonts are really fuzzy because of a drop shadow effect I put on the style. Initially all the controls had an explicit drop shadow effect as part of the style, but I fixed this by removing the drop shadow effect from the controls and moved it to Rectangles with the same drop shadow.
Then I place the Rectangle directly behind the textboxes - I still have the visual effect and the fonts in the overlaying controls looked great.
<DropShadowEffect x:Key="dropShadow" Color="Gray" Opacity=".50" ShadowDepth="8" />
<Style x:Key="BackingRectangleStyle" TargetType="Rectangle">
<Setter Property="Effect" Value="{StaticResource dropShadow}" />
</Style>
<Rectangle Grid.Row="1" Grid.Column="3" Style="{StaticResource BackingRectangleStyle}"/>
<TextBox Grid.Row="1" Grid.Column="3" ... />
However, I have the same problem with foggy fonts with DatePicker TextBoxes since the drop shadow effect is still directly on the control.
I do not have a DatePicker style, but I do have a style of the DatePickerTextBox, which is where the effect comes from.
<Style TargetType="{x:Type DatePickerTextBox}">
<Setter Property="Effect" Value="{StaticResource dropShadow}" />
</Style>
What I don't know how to do is to follow my previous pattern of removing the effect, creating a Rectangle with the same effect and placing it behind the DatePicker TextBox so it's the same size, etc. I need a little help on the XAML to do so.
Can anyone provide me any advice?
Thanks!
Because knowlege about TextFormattingMode really needs spreading, I decided to post the following - even though it strangely doesn't help with the DatePickerTextBox, which is still fuzzy. It prevents you from the stunt you pulled with the rectangle behind the TextBox though.
Unless you have large, or transformed text, always use TextOptions.TextFormattingMode="Display" in your outermost WPF container.
This was introduced in WPF 4.0, and I suppose the default "Ideal" reflects earlier versions, but what a mind-boggling mistake that is...
<Window x:Class="WpfApplication1.MainWindow" x:Name="MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="400"
TextOptions.TextFormattingMode="Display"> <!-- Please notice the effect of this on font fuzzyness -->
<Grid>
<Grid.Resources>
<DropShadowEffect x:Key="DropShadow" Color="Gray" Opacity=".5" ShadowDepth="8"/>
</Grid.Resources>
<TextBox Text="Really Sharp" HorizontalAlignment="Center" Padding="3" VerticalAlignment="Center" Effect="{StaticResource DropShadow}"/>
</Grid>
</Window>

Binding ContentPresenter.Content to TemplatedParent (WPF/Silverlight)

Basically, I would like to overlay, for example: TextBlock over Button, by using ControlTemplate (applied to this Button), but I don't want to get rid of default template of it.
Example:
<Grid Grid.Row="1" Grid.ColumnSpan="2">
<Grid.Resources>
<Style x:Key="myStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<ContentPresenter />
<TextBlock Text="textBlock"
Margin="10" Foreground="Red"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Button Style="{StaticResource myStyle}" Content="button1"></Button>
</Grid>
and it gives Button stripped of it's default template:
Rather, I would like to receive something like this:
Is it possible by using ControlTemplate? I was trying to bind TemplatedParent to ContentPresenter.Content like here:
<ContentPresenter Content="{Binding
RelativeSource={RelativeSource Mode=TemplatedParent},
Path=.,
Mode=TwoWay}"/>
or other combinations, but I couldn't make it work.
Edit:
Because I would like to be able to apply this TextBlock not only to a button (it was just an example) but to any Control, I don't want do it by copying default style (to the resources or somewhere), for every Control.
Also, I would prefer not to create UserControl, because I would like to keep xaml clean as much as possible (I mean with system Controls) - and just to turn on/off the overlaying TextBlock by using a ControlTemplate.
You could add the default style on the button and modify it to add your TextBlock. The second option, my preference, is to create a new UserControl that will contain the Button and the TextBlock with IsHitTestVisible=False. You can then add dependency properties to be able to bind to the button and the text block.

Reset Style in certain portion of Visual Tree in WPF

I am setting some global styles for TextBox, ComboBox, TextBlock, etc. in my App.xaml file. I want these styles to flow down through the visual tree for a consistent look and that is what they are doing.
However, I am using a Ribbon in part of my UI. The style customizations are completely throwing off the appearance of the Ribbon. The ribbon sits at the same level as many other UI elements so is there a way to just reset the style for the ribbon and its visual children
I don't think that you can change this wpf behaviour.
But you can try to contain all global styles to specific resource dictionary and use it in all other VisualTree elements.
Or you can try something like this:
<Window ...>
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Red" />
</Style>
</Window.Resources>
<DockPanel LastChildFill="True">
<Button x:Name="button1" Content="button" DockPanel.Dock="Top" />
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Button">
</Style>
</StackPanel.Resources>
<Button x:Name="button2" Content="lala" />
</StackPanel>
</DockPanel>
</Window>
Element with name "button2" will be default.

Styling a Textblock autogenerated in a ContentPresenter

As I saw, a lot of people ran into this exact problem but I can't understand why my case is not working and it is starting to drive me crazy.
Context: I have a DataGrid which is to be colored according to the values of each cell. Hence, I have a dynamic style resolving the actual template to be used for each cell. Backgrounds now work accordingly.
New problem: when I have a dark background, I want the font color to be white and the font weight to be bold so the text is correctly readable. And... I can't style it correctly.
I read some Stackoverflow posts about that:
This one fits my problem but doesn't provide me any working solution
This one is also clear and detail but... duh
This is almost the same problem as me but... Solution does not work
Here is what I tried so far:
<!-- Green template-->
<ControlTemplate x:Key="Green" TargetType="{x:Type tk:DataGridCell}">
<Grid Background="Green">
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ContentPresenter.Resources>
<Style BasedOn="{StaticResource BoldCellStyle}" TargetType="{x:Type TextBlock}" />
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
</ControlTemplate>
Does not work. Background is green, but text stays in black & not bold.
BTW, the BoldCellStyle is as easy as it can be:
<Style x:Key="BoldCellStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="White" />
</Style>
Okay. Second try (which is a real stupid one but well...)
<!-- Green template -->
<ControlTemplate x:Key="Green" TargetType="{x:Type tk:DataGridCell}">
<Grid Background="Green">
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ContentPresenter.Resources>
<Style x:Key="BoldCellStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="White" />
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
</ControlTemplate>
Doesn't work either.
Then, I tried to play with the ContentPresenter's properties:
<!-- Green template -->
<ControlTemplate x:Key="Green" TargetType="{x:Type tk:DataGridCell}">
<Grid Background="Green">
<ContentPresenter TextElement.FontWeight="Bold" TextElement.Foreground="White" TextBlock.Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
And... As you can expect, this does not even work.
Intrigued, I used Snoop to browse all the components of my interface.
In the first two cases, Snoop actually shows me that each cell is a Grid with a ContentPresenter containing a TextBlock and the actual Style but... The TextBlock's properties do not apply and FontWeight is still normal.
Last case, even more shocking, I can see that snoop shows me that we actually have a ContentPresenter with the right properties (ie TextElement.FontWeight="Bold"), but the autogenerated TextBlock under is - still - not styled.
I can't get what am I missing here. I tried as you can see almost all I could possibly do here, and the TextBlocks keep being non-formatted.
Any idea here? Thanks again!
The DataGridColumns that derive from DataGridBoundColumn (all except DataGridTemplateColumn) has a property ElementStyle that is applied to the TextBlock when it is created. For e.g. DataGridTextColumn It looks like this
static DataGridTextColumn()
{
ElementStyleProperty.OverrideMetadata(typeof(DataGridTextColumn),
new FrameworkPropertyMetadata(DefaultElementStyle));
// ...
}
It overrides the metadata for ElementStyle and provides a new default value, DefaultElementStyle, which basically just sets the default margin for the TextBlock.
public static Style DefaultElementStyle
{
get
{
if (_defaultElementStyle == null)
{
Style style = new Style(typeof(TextBlock));
// Use the same margin used on the TextBox to provide space for the caret
style.Setters.Add(new Setter(TextBlock.MarginProperty, new Thickness(2.0, 0.0, 2.0, 0.0)));
style.Seal();
_defaultElementStyle = style;
}
return _defaultElementStyle;
}
}
This style is set in code everytime a new DataGridCell is created with element.Style = style; and this is overriding the Style you are trying to set, even if you try to set it implicitly.
As far as I know, you'll have to repeat this for your columns
<DataGridTextColumn Header="Column 1" ElementStyle="{StaticResource BoldCellStyle}" .../>
<DataGridTextColumn Header="Column 2" ElementStyle="{StaticResource BoldCellStyle}" .../>

Why does the style change when I add an an accelerator to my button?

When I have my button's content as a normal string e.g. <Button Content="Ok" /> then button behaves as normal. But if I change the content to have a keyboard accelerator e.g. <Button Content="_Ok" /> the button's style changes to have different margins and sizes.
I have a TextBlock style that doesn't have a key so is being applied to all TextBlocks, my question is why is it applied when it the content has an accelerator and not when it doesn't?
Edit: For extra info: The default style is inside the resources of a StackPanel that is the button is inside. I guess the question is really, why doesn't the default TextBlock style get applied when the button has an accelerator?
WPF adds a TextBlock to each Button (and Menu) with an accelerator.
You can see this effect by running the following XAML (remember to hook up the Command if needed).
The key to fixing the problem, given the scope of your question, is to set the TextAlignment to a value of Center for the TextBlock. If you set the Width for the TextBlock style (my line is commented out below) the text will start to shift. Adding HorizontalAlignment = Center also helps center text in the TextBlock/Button, but this also impacts the other TextBlock controls.
<Window x:Class="ButtonAccelerator.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Main Window" Height="400" Width="800">
<Window.Resources>
<Style TargetType="TextBlock">
<!--<Setter Property="Width" Value="70"/>-->
<Setter Property="Height" Value="23"/>
<Setter Property="Background" Value="Pink"/>
<Setter Property="TextAlignment" Value="Center"/>
</Style>
<Style TargetType="Button">
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="23"/>
</Style>
</Window.Resources>
<DockPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel
Grid.Row="1" Grid.Column="1"
HorizontalAlignment="Right"
Orientation="Horizontal">
<TextBlock Text="OK" />
<Button
Content="OK"/>
<Button
Content="_OK"/>
</StackPanel>
</Grid>
</DockPanel>
</Window>
You should verify this with Snoop but <Button Content="Ok" /> produces a TextBlock to handle the text within a button. Since TextBlock doesn't support accelerator keys I would bet that <Button Content="_Ok" /> causes it to produce a Label instead since a Label will take care of the accelerator key.

Resources