I try to find how I can update the Width and Height properties of my custom control.
I have used the RadialProgressBar implementation found in UWP Community Toolkit pull request #828 for 1.5 milestone.
I can set the Width and Height on the custom control and it will work but I need to set different Width and Height values depending on the display resolution.
RadialProgressBar.xaml
RadialProgressBar.cs
Page.xaml
I'm doing something wrong I think but I can't find what.
Any idea?
I found the solution in the answer to this question UWP XAML Change Style of a target with VisualStateManager.
I need to put the VisualStateManager in the Template of the control.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:RadialProgressBar">
<Grid x:Name="Grid">
<!-- Put the VisualStateManager definition here -->
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
I have updated RadialProgressBar.xaml file in my gist.
Related
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.
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.
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.
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.
Could you tell me what is the main differences between Style and ControlTemplate ?
When or why to use one or the other ?
To my eyes, they are exactly the very same. As I am beginner I think that I am wrong, thus my question.
In a style you set properties of a control.
<Style x:Key="MyButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Red"/>
</Style>
<Button Style="{StaticResource MyButtonStyle}"/>
All buttons that use this style will have their Backgrounds set to Red.
In a template you define the UI (structure) of the control.
<ControlTemplate x:Key="MyButtonTemplate" TargetType="Button">
<Grid>
<Rectangle Fill="Green"/>
<ContentPresenter/>
</Grid>
</ControlTemplate>
<Button Template="{StaticResource MyButtonTemplate}"/>
All buttons that use this template will have a green background that cannot be changed.
Values set in a template can only be replaced by replacing the entire template. Values in a style can be replaced by setting the value explicitly when using the control. That is why is better to use the properties of the control by using TemplateBinding instead of coding values.
<ControlTemplate x:Key="MyButtonTemplate" TargetType="Button">
<Grid>
<Rectangle Fill="{TemplateBinding Background}"/>
<ContentPresenter/>
</Grid>
</ControlTemplate>
Now the template uses the value of the Background property of the button it is applied to, so it can be customized:
<Button Template="{StaticResource MyButtonTemplate}" Background="Yellow"/>
Another useful feature is that controls can pick up a default style without having a specific style being assigned to them. You can't do that with a template.
Just remove the x:Key attribute of the style (again: you can't do this with templates). All buttons in the visual tree below the style will have this style applied.
Combining Templates and Styles is extra powerful: you can set the Template property in the style:
<Style TargetType="Button">
<Setter Property="Background" Value="Red"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Rectangle Fill="{TemplateBinding Background}"/>
<ContentPresenter/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
No indeed you are quite wrong.
Styles set properties on controls. ControlTemplate is a property shared by most controls that specify how they are rendered.
To elaborate, you can use a style to group settings for a bunch of properties so you can re-use that to standardize your controls. Styles can be set explicitly on controls or applied too all of a certain type.
Control Templates can be set by a style or set explicitly on a control to change the way it appears. All controls have default templates (and styles for that matter) that are embedded in the .net wpf assemblies. It is quite enlightening to see these and understand how the wpf developers implemented the normal versions of all controls. If you have Expression blend installed, look in its "SystemThemes" folder.
UPDATE:
To understand how Styles and ControlTemplates can "add controls". In some way or another, the ControlTemplate is the only way to define the controls a control is made up of. But, some default .net controls allow you to use controls in place of text.
For example:
<GroupBox>
<GroupBox.Header>
<CheckBox/>
</GroupBox.Header>
</GroupBox>
This "adds" a checkbox to the groupbox without changing the ControlTemplate, but this is because the default ControlTemplate for GroupBox allows anything as the Header. This is done by using special controls such as ContentPresenter.
However, sometimes the default ControlTemplate for a control doesn't allow you to change something that you want to change via properties. Then you must change the ControlTemplate.
Whether you set the Properties of a control (Content, Header, ControlTemplate, IsEnabled, etc.) directly or via a style does not matter, Styles are only a convenience.
Hopefully this answers your question more clearly.
You can think of a Style as a convenient way to apply a set of property values to more than one element. You can change the default appearance by setting properties, such as FontSize and FontFamily, on each TextBlock element directly. However, if you want your TextBlock elements to share some properties, you can create a Style in the Resources section of your XAML file.
On the other hand, a ControlTemplate specifies the visual structure and visual behavior of a control. You can customize the appearance of a control by giving it a new ControlTemplate. When you create a ControlTemplate, you replace the appearance of an existing control without changing its functionality. For example, you can make the buttons in your application round instead of the default square shape, but the button will still raise the Click event.
Ref: http://msdn.microsoft.com/en-us/library/ms745683.aspx
I found some interesting differences in
The difference between styles and templates (msdn)
Style:
You can set only pre-existing properties in the style. For example, you cannot set a default value for a property that belongs to a new part that you added to the template.
Template:
When you modify a template, you have access to more parts of a control than when you modify a style. For example, you can change the way the pop-up list appears in a combo box, or you change the look of the button that triggers the pop-up list in the combo box by modifying the items template.
Style:
You can use styles to specify the default behavior of a control. For example, in a style for a button, you can specify a trigger so that when users move their mouse pointer over the button, the background color will change. These property changes are instantaneous (they cannot be animated gradually).
Template:
You can specify the behavior of any new and existing parts in a template by using triggers. For example, you can specify a trigger so that when users move their mouse pointer over a button, the color of one of the parts will change. These property changes can be instantaneous or animated gradually to produce a smooth transition.
OK, I had the exact same question and the answers I found in this thread pointed me in the right direction so I'm sharing, if only so I can understand it better myself.
A Style is more flexible than a ControlTemplate.
From Windows Presentation Foundation Unleashed, Adam Nathan and gang (writers) state this:
"Besides the convenience of combining a template [with a style using the Style's ControlTemplate setter] with arbitrary property settings, there are important advantages of doing this [setting the ControlTemplate setter on a style]:
It gives you the effect of default templates. For example, when a typed Style gets applied to elements by default, and that Style contains a custom control template, the control template gets applied without any explicitly markings on those elements.
It enables you to provide default yet overridable property valus that control the look of the template. In other words, it enables you to respect the templated parent's properties but still provide your own default values."
In other words, creating a style allows the user of the Style's Template setter to override the values set, even if they did not use a TemplateBinding ({TemplateBinding Width} for example). If you hardcoded the Width in your style, the user of the Style could still override it, but if you hardcoded that Width property in a Template, the user is stuck with it.
Also, (and this is kind of confusing) when using a ContentTemplate with a TemplateBinding the onus is on the user to set that property otherwise it will use the default property for the TargetType. If you use a style, you can override the default property of the TargetType by using a setter for the property and then applying a TemplateBinding referencing back to that setter. The book explains it better, page 338 (Mixing Templates with Styles)