Set the width of scrollbars programmatically - c#

I have an application, which uses WPF on windows as toolkit framework. Now I would like to set the width of scrollbars for my ScrollViewers programmatically. I found many examples to set the width via XAML. But how can I define the width of scrollbars programmatically?
Unfortunately I could not find any property or method on ScrollViewer to set the width of scrollbars.
var viewer = new ScrollViewer();
viewer.MagicProperty = 42; // Does not exist
Also all properties on SystemParameters are unfortunately read-only.
VerticalScrollBarWidth.VerticalScrollBarWidth = 42; // Read-only
Edit: WPF is only one of multiple toolkit frameworks in my application. I use a custom GUI abstraction layer for supporting Windows (WPF), Linux (GTK#) and MacOS X (in future). My user interface is encapsulated in an OS independent way. Therefore it makes no sense to use XAML.

Easiest way is to set x:Name property, then you can access ScrollViewer in your code.
Or use Binding: http://www.tutorialspoint.com/wpf/wpf_data_binding.htm
Binding will be useful if you want to manipulate with multile ScrollViewers and set same values.
EDIT:
You can create ScrollViewer in your code and then set its parameters. But you need a way to insert it into VisualTree among other controls. So you need to get instance of some container and then use its Children.Add() method
However I'd really recommend to use as much XAML as you can and leave your code for application logic, not the UI building.
EDIT 2:
Can you try:
Style myStyle = new Style(typeof(ScrollBar));
myStyle.Setters.Add(new Setter(WidthProperty, 40));
scrollViewer.Style = myStyle;
EDIT 3:
I found a solution. You can add ResourceDictionary.xaml and add this style to it:
<Style x:Key="{x:Type ScrollBar}" TargetType="{x:Type ScrollBar}">
<Setter Property="MinWidth" Value="35" />
<Setter Property="Width" Value="35" />
</Style>
Then load it at runtime like so:
Resources.MergedDictionaries.Add(Application.LoadComponent(new Uri(#"Dictionary.xaml", UriKind.Relative)) as
ResourceDictionary);

Related

UWP Style X:binding of margin to a function throws a System.AccessViolationException. Any ideas why, when this works fine if set in inline xaml?

I have some methods that I x:bind to, to set element size based on the size of the host control. All works well except when binding a function to the Margin property in my user control (from style dictionary) I am getting a System.AccessViolationException.
I do not get the exception if binding to the element directly -just when used in a style setter. Obviously can work around this by setting the property on the xaml for the object but would like to know if this is a bug or if I am missing something? The function binding from the dictionary works with all other properties that I am using (just not on Margin). Any advice or guidance would be appreciated.
XAML Snippet:
<UserControl.Resources>
<ResourceDictionary>
<Style TargetType="Path" x:Key="Ball.Shadow">
<Setter Property="Height" Value="{x:Bind DimensionAsFraction(0.5)}" />
...
</Style>
<Style TargetType="TextBlock" x:Key="Ball.Letter" BasedOn="{StaticResource Ball.Text}">
<Setter Property="Margin" Value="{x:Bind MarginAsFraction(0.075), Mode=OneWay}" />
...
</style>
object.Height is the height of the host control - this has been set
before the component is initialised and works fine when referenced
from other code and style setters.
Code Snippet:
public sealed partial class Example : UserControl
{
private void SetDefaults()
{
Height = 200;
Width = 200;
}
private int calculateAsInt(double fraction) => (int)(object.Height * fraction);
private double DimensionAsFraction(double fraction) => calculateAsInt(fraction);
private Thickness MarginAsFraction(double fraction) => new Thickness(0, calculateAsInt(fraction), 0, 0);
private Thickness BorderAsFraction(double fraction) => new Thickness(calculateAsInt(fraction));
public Example()
{
SetDefaults();
this.InitializeComponent();
}
}
Thanks :D
UWP Style X:binding of margin to a function throws a System.AccessViolationException. Any ideas why, when this works fine if set in inline xaml?
I'm afraid you can't use binding or x:bind in the style setter, derive from official document
Windows Presentation Foundation (WPF) and Microsoft Silverlight supported the ability to use a Binding expression to supply the Value for a Setter in a Style. The Windows Runtime doesn't support a Binding usage for Setter.Value (the Binding won't evaluate and the Setter has no effect, you won't get errors, but you won't get the desired result either). When you convert XAML styles from Windows Presentation Foundation (WPF) or Microsoft Silverlight XAML, replace any Binding expression usages with strings or objects that set values, or refactor the values as shared {StaticResource} markup extension values rather than Binding -obtained values.
For this scenario, we suggest set margin in the control directly
<TextBlock Text="Hello World" Margin="{x:Bind MarginAsFraction(0.75)}" />
I stumbled on this thread attempting to solve a similar problem which resulted in a Stack Overflow Error:
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="{x:Bind MyMargin, Mode=OneWay"/>
</Style>
For my use case, I did not feel that setting the control's margin was appropriate because doing so meant that the selection box (when using then keyboard) was not around the control, but the control and margin. Since I have a non-uniform margin, it did not look right.
My solution was to set in code behind in the Page SizeChanged event (since that is when and why I am changing the margin).
Dim Width As Integer = SomeFunctionOf(WindowSize.Width)
Dim NewMargin As New Thickness(Width, 0, Width, 0)
Dim MarginStyle As New Style(GetType(GridViewItem))
MarginStyle.Setters.Add(New Setter(MarginProperty, NewMargin))
MyGridView.ItemContainerStyle = MarginStyle
Not optimum, but it worked for me. Perhaps this will help someone in the future.
--- Update ---
After I posted this, I got to thinking about it and realized I could use the same code above, but instead of setting MyGridView.ItemContainerStyle in code, I could instead set a Property in my ViewModel, such as MyViewModel.MarignStyle = MarginStyle. Then, use binding with:
<GridView x:Name="MyGridView" ItemsSource="{x:Bind MyViewModel.ItemsView, Mode=OneTime}" ItemContainerStyle="{x:Bind MyViewModel.MarginStyle,Mode=OneWay}">
In any case, both versions work for me.

UWP - Subclassing built-in controls and inheriting styling behaviors

Is it possible to subclass a control (AppBarToggleButton in my case) and "inherit" TargetType of the base class? What I want to achieve is to have a slightly customized AppBarToggleButton (with disabled auto-toggle behavior) put into CommandBar and make it look exactly as if it was regular AppBarToggleButton (i.e. receive style whatever is defined for AppBarToggleButton inside given command bar control template). They say, DefaultStyleKey should help, but it is inherited fine, but, alas, doesn't seem to participate in local style resolution/lookup.
I may need to subclass other controls for various purposes, so the ultimate goal here is to understand how local style resolution works internally and does target instance has any involvement in it or is it a completely external process.
In general, we need make Templated Control for custom AppBarToggleButton. When we make Templated Control with Visual Studio, it will generate Generic.xaml file in the Themes folder that used to declare the custom control's style. And the the custom control cs file like the following.
public sealed class CustomAppBarToggleButton : AppBarToggleButton
{
public CustomAppBarToggleButton()
{
this.DefaultStyleKey = typeof(CustomAppBarToggleButton);
}
}
If you don't want to edit the default style you could remove DefaultStyleKey line that used to binding current control with the style in the Generic.xaml file.
Open Generic.xaml file you will find the following. And it's empty style. If we want to do some small changes, you need copy the complete AppBarToggleButton style to replace it and edit the TargetType to local:CustomAppBarToggleButton. Then you can edit the style base on your requirement.
<Style TargetType="local:CustomAppBarToggleButton" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CustomAppBarToggleButton">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And if your want to make a new dependency property, please define it in the cs file then use TemplateBinding to bind the property in the style. For more please check this document.
For anyone still stumbling upon this. I managed to solve a similar issue, inheriting from Button, using the approach described here https://stackoverflow.com/a/71338869/10468107
Specifically, adding
<Style BasedOn="{StaticResource DefaultButtonStyle}" TargetType="local:MyButton" />
solved it for me. So maybe it works for other types as well, using {StaticResource Default<TYPE>Style}
I have a similar need and am wondering if the answer is still the same. I have extended the basic ComboBox control to meet some behavioral requirements.
class ExtendedComboBox : ComboBox
I want the ExtendedComboBox instances to inherit the latest platform styling but they are instead getting styled differently. The first of these is an ExtendedComboBox (square corners, larger glyph), while the second is a generic ComboBox (rounded corners, smaller glyph).
The requirement is to have the two combo boxes styled the same way. I am reluctant to create an explicit Style for ExtendedComboBox because then if the style for the generic ComboBox changes the ExtendedComboBox will no longer match. Is there some way to just inherit the standard style?

Set button style in code behind

How can I set the style of a Button? I use Xceed.wpf.toolkit
Xceed.Wpf.Toolkit.MessageBox mbox = new Xceed.Wpf.Toolkit.MessageBox();
System.Windows.Style style = new System.Windows.Style(typeof(System.Windows.Controls.Button));
style.Setters.Add( new System.Windows.Setter(System.Windows.Controls.Button.ForegroundProperty, Brushes.DarkGreen));
mbox.OkButtonStyle = style;
I get the error
System.Windows.Markup.XamlParseException: ''System.Drawing.SolidBrush' is not a valid value for the 'System.Windows.Documents.TextElement.Foreground' property on a Setter.'
Be sure to use the WPF libraries and not the WindowsForms or GDI+ ones...
What you should use: System.Windows.Media.Brushes which contains DarkGreen as System.Windows.Media.SolidColorBrush (in PresentationCore.dll).
What you currently use is System.Drawing.Brushes and System.Drawing.SolidBrush.
TextElement.Foreground is of type System.Windows.Media.Brush. That's it's "data type". You have to assign it a value of that type, or some subclass of that type.
System.Drawing.Brushes.DarkGreen is of type System.Drawing.Brush, which is not a subclass of System.Windows.Media.Brushes. That's from Windows Forms or something, not WPF. You need to use a WPF brush object for a WPF control.
Get rid of using System.Drawing; at the top of your C# file. In a WPF project, that'll cause you nothing but trouble. Use System.Windows.Media.Brushes.DarkGreen instead.
style.Setters.Add( new System.Windows.Setter(System.Windows.Controls.Button.ForegroundProperty,
System.Windows.Media.Brushes.DarkGreen));
You could also create the Style as a XAML resource and load it with FindResource(). Then you'd just say "DarkGreen" and let the XAML parser worry about what kind of brush to create:
<Style
x:Key="XCeedMBoxButtonStyle"
TargetType="{x:Type Button}"
BasedOn="{StaticResource {x:Type Button}}"
>
<Setter Property="TextElement.Foreground" Value="DarkGreen" />
</Style>
C#
var style = FindResource("XCeedMBoxButtonStyle") as Style;
But then you've got to worry about defining it someplace where it can be found, and what you're doing will work OK anyhow if you just use the right Brush class.
It's pretty gruesome that we've got multiple classes called Brush in multiple .NET namespaces with uninformative names like "System.Windows.Media" vs "System.Drawing", but unfortunately it all just sort of grew that way.

customize Style CheckList RadTreeView

Is there a way to change the style of checkboxes when the ItemsOptionListType="CheckList"
inside a RadTreeView?
There are a couple of ways of doing this that I can think of, but sadly neither of them is particularly easy.
One way is to use Blend or a similar tool to obtain the template for the RadTreeViewItem class. The RadTreeViewItem class and its template are in the Telerik.Windows.Controls.Navigation assembly. Take a copy of this template and modify the CheckBox within this template to customise its appearance as you wish.
To use the template, add a ControlTemplate and a Style to the <UserControl.Resources> element of a XAML page, as follows:
<UserControl.Resources>
<ControlTemplate x:Key="myRadTreeViewItemTemplate" TargetType="telerik:RadTreeViewItem">
<!-- modified template goes here... -->
</ControlTemplate>
<Style TargetType="telerik:RadTreeViewItem">
<Setter Property="Template" Value={StaticResource myRadTreeViewItemTemplate}" />
</Style>
</UserControl.Resources>
This should then apply the modified template to any RadTreeViews in the same XAML file.
Note that we have to use an implicit style (i.e. one without an x:Key), since there seems to be no other way to tell a RadTreeView to apply a given style to its child items.
Alternatively, you can modify a built-in theme. This approach could also change the styles of CheckBoxes used within other Telerik controls in your application, for example in a GridViewCheckBoxColumn within a RadGridView.
EDIT: if you want the template for the CheckBox as used in the RadTreeView by default,
you'll find it in Themes\Office\Black\System.Windows.Controls.xaml within the Telerik.Windows.Controls assembly. This assumes you're using the 'Office Black' theme; adjust the path of this file if you're using a different Telerik theme.

Difference between Style and ControlTemplate

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)

Categories

Resources