Dynamically change between .ttf files Xamarin Forms - c#

I'm using a custom font in my app and need change the font attribute to bold which as far as I can tell is not done simply.
I have already managed to dynamically change colour and attributes for the default font using the resource dictionary:
<Color x:Key="LabelColor">White</Color>
<FontAttributes x:Key="LabelFontAtt">None</FontAttributes>
and then using MVVM changing the colour and attribute in my ViewModel:
App.Current.Resources["LabelColor"] = Xamarin.Forms.Color.FromHex("#01bf89");
App.Current.Resources["LabelFontAtt"] = FontAttributes.Bold;
From a previous question I've already learned how to set my custom font as default for all labels with:
<Style TargetType="Label">
<Setter Property="FontFamily">
<Setter.Value>
<OnPlatform x:TypeArguments="x:String">
<OnPlatform.Android>JosefinSlab-Regular.ttf#JosefinSlab-Regular</OnPlatform.Android>
</OnPlatform>
</Setter.Value>
</Setter>
</Style>
I would like to switch between JosefinSlab-Regular.ttf and JosefinSlab-Bold.ttf but I've had little success with doing so. Is it possible to do it in a variation of what I've already done with attributes and colour or should it be done another way?

In your current setup you could create a second style like such:
<Style TargetType="Label" x:Key="BoldLabel">
<Setter Property="FontFamily">
<Setter.Value>
<OnPlatform x:TypeArguments="x:String">
<OnPlatform.Android>JosefinSlab-Bold.ttf#JosefinSlab-Bold</OnPlatform.Android>
</OnPlatform>
</Setter.Value>
</Setter>
</Style>
And then swap out the Style the same way you swap out the TextColor based on the Key in the Style.
I obviously don't know what functionality you're trying to implement but from what you're saying it seems like you're putting UI logic (such as colors) in your ViewModel which goes against how MVVM should be used in Xamarin Forms. If you want to change colors and styles based on data in your ViewModel you could also look into Triggers which is something that exists on the UI side only so you get a clean separation of ViewModel logic and UI logic.

Related

How to apply style in WPF to all controls without overriding their original styles?

I want to create a style, which will normalize margins for all controls in a specific scenario:
<Style TargetType="FrameworkElement" x:Key="MyStyle">
<Setter Property="Margin" Value="{StaticResource DialogItemsExceptTopMargin}" />
</Style>
I have then a couple of different controls: textboxes, comboboxes, checkboxes etc., to which I want to apply this style.
However, when I do that, their look is immediately reverted to the platform style (I am applying a style from 3rd party library). How can I define my style so that the original styles are kept intact?
Mind: I know, that I can use BasedOn for specific type:
<Style TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
...
</Style>
This however would require me to create completely separate styles for all possible controls, which I may use. I tried this trick with FrameworkElement and Control, but I got an error, that there is no such StaticResource.

WPF Override Style Value

I'm using MaterialDesignInXaml for WPF which provides 3rd party controls and styles. I need to edit one of these styles by changing one property.
I am using an Expander control which has a template creating a bunch of child controls. I've discovered the child 'Border' control (4 layers deep) has the property (padding) which I need to set to zero.
See this output from Snoop showing the property I need to change:
Link to image
My question is how can I do this? I've tried extending the style used by the control as follows, but it isn't changing anything so I assume I'm doing something wrong?
<Style TargetType="{x:Type Expander}"
x:Key="MaterialDesignExpanderHeadless"
BasedOn="{StaticResource MaterialDesignExpander}">
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="Padding" Value="0"></Setter>
</Style>
</Style.Resources>
</Style>
I am able to use the style like this. And I know this is working for sure:
<Expander Header="Header Content" Style="{StaticResource MaterialDesignExpanderHeadless}">
Some Content
</Expander>
You're right, this method should work. Something else is setting the border's padding.
Snoop is telling you the padding is defined by the parent template, which could be the HeaderSite (ToggleButton).
You could try to extend the ToggleButton style (BasedOn) or redefine it locally.

Accessing elements in a xaml defined style

I have followed the DiagramDesigner example on Codeproject for learning how to use Adorners in WPF as it fits quite a few of my needs relatively closely.
I have adapted the implementation a little, and also added my own adorner, for controlling the opacity of a control via a slider (slider on the adorner).
Following the same methods as the author, I placed the slider and other feature in a xaml style definition file as below. I am just now struggling A) to figure out how to access the slider at any level, B) how best to start hooking this up with an underlying Viewmodel that will be used for various settings (on adorners).
<Style x:Key="OpacityAdorner" TargetType="{x:Type adorners:OpacityChrome}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type adorners:OpacityChrome}">
<Grid>
<Slider x:Name="OpacitySlider" Style="{StaticResource OpacityControl}" ToolTip="Alter the opacity of the image to overlay with other images" Visibility="Collapsed"/>
<Ellipse x:Name="OpacitySliderEnable" Style="{StaticResource OpacityIcon}" ToolTip="Alter the visual opacity of the image" Visibility="Visible"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The codeproject example is here http://www.codeproject.com/Articles/22952/WPF-Diagram-Designer-Part
A) Use something like the following snippet to get the slider from the applied template.
var slider = opacityAdorner.Template.FindName("OpacitySlider", opacityAdorner) as Slider;
there are cases where the template has not yet been applied, in that case you need to preceed the previous call with the following:
opacityAdorner.ApplyTemplate();
B) The best approach for hooking up with the view model (in my opinion) is to expose the required properties as dependency properties on the OpacityChrome adorner. You then use normal Binding to hook up the new properties to the view-model, and TemplateBinding to hook them up to the template elements.

Template for basic reusable button

In WPF (VS2013), I'm creating a button like so:
<Button>
<Label>1</Label>
</Button>
Each of these buttons will have more to it, such as increased font size of the Label, grid row/column assignment, and I might use a binding for the label so that I can change the number. I'm creating a calculator app so I need to reuse this button 10 times (one for each number 0-9). Instead of copying/pasting this button XML 10 times, I wanted to see if I could templatize it.
I've read a little about ControlTemplate and DataTemplate, but I'm not sure if either of these are the correct thing to use. It's also not clear to me what should be a style or what should be a template.
So if someone could help me understand how to "templatize" the button and its styles (e.g. width, height, font size, etc) so that they can be easily reused, that would help a ton. Guidance is appreciated!
Use a ControlTemplate when you want to overwrite the entire template for a control, use a DataTemplate when you want to tell WPF how to draw a data object (usually the DataContext), and use ContentTemplate when you want to tell WPF how to draw the Content property of an object.
Creating a whole new ControlTemplate is quite complex. To demonstrate, check out this MSDN example for an example ControlTemplate for a Button.
In your case, I would recommend creating a Style for your button with setters for common properties such as Height, Width, Font, etc. If you want to draw your button's Content property in a custom way without completely overwriting the button template, include a ContentTemplate style setter to tell WPF how to draw the Button.Content property.
<Button Style="{StaticResource CalculatorButton}" Content="1" />
and
<Style x:Key="CalculatorButton" TargetType="{x:Type Button}">
<Setter Property="Height" Value="50"/>
<Setter Property="Width" Value="50"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding }" FontFamily="Wingdings 3" FontWeight="Bold" FontSize="18" Foreground="Navy" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
The ControlTemplate defines how the button looks, the ContentTemplate defines how the Button.Content looks, and the DataTemplate used for the ContentTemplate is defining how the data object of "1" will be drawn.
You can start with a copy of the style of the button. Use Blend (part of VS) to create that: open the context menu of the button inside the object tree, then select "Edit template" (or similar, don't have an english version at hand), then "Copy of template" (or alike).
Now you may change properties (in designer or XAML). Every button that shall have this style needs to reference this new ressource.
You need to create a new Style of a button. Learning curve is not too steep, but the benefits are enormous. You can start learning about it here: http://msdn.microsoft.com/en-us/library/ms745683(v=vs.110).aspx
Long story short: Open your project with Blend, right-click on your button, "Edit Style", "Edit a copy". If you choose to define it in Application, you can reuse it among other pages (it will be then in you App.xaml file)
Once you have the base style, edit it as much as you need.

What is the recommended way to skin an entire application in WPF?

I want my WPF application to be skinnable, by applying a certain XAML template, and the changes to be application wide, even for dynamic controls or controls that aren't even in the visual/logical tree.
What can I use to accomplish this type of functionality? Are there any good resources or tutorials that show how this specific task can be done?
The basic approach to take is using resources all through your application and dynamically replacing the resources at runtime.
See http://www.nablasoft.com/alkampfer/index.php/2008/05/22/simple-skinnable-and-theme-management-in-wpf-user-interface/ for the basic approach
The replacing of resource will work but I found "structural skinning" to be more powerfull! Read more about it on CodeProject...
http://www.codeproject.com/KB/WPF/podder1.aspx
I have found the way to apply generic templates to all controls without using template keys. The solution is to use the type of the control as the Style key.
Example:
<Application.Resources>
<Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
<Setter Property="Button.Background" Value="CornflowerBlue"/>
<Setter Property="Button.Template">
<Setter.Value>
<ControlTemplate x:Name="MyTemplate">
...
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
here the Style key is x:Key="{x:Type Button}", so the style will be applied to all controls of type button without the control declaring the Style property to be a static or dynamic resource.

Categories

Resources