Following a problem in WPF 4 where the default ProgressBar template has an off-white highlight applied causing it to dull the foreground colour, I decided to extract the template and manually edit the values to white.
After doing this, I put the template as a style in App.xaml for global use and the Visual Studio designer began to use it right away.
However, when I run my app, the default style is still being applied:
(source: nidonocu.com)
I then tried setting the style specifically using a key, then even having it as an inline style and finally as a inline template without a wrapping style for the specific progress bar and it is still ignored.
What's going wrong?
Current code for the ProgressBar:
<ProgressBar Grid.Column="1"
Grid.Row="2"
Height="15"
Width="355"
Margin="0,0,0,7"
IsIndeterminate="{Binding ProgressState, FallbackValue=False}"
Visibility="{Binding ProgressVisibility, FallbackValue=Collapsed}"
Value="{Binding ProgressValue, Mode=OneWay, FallbackValue=100}"
Foreground="{Binding ProgressColor,FallbackValue=Red}">
<ProgressBar.Template>
<ControlTemplate>
<Grid Name="TemplateRoot"
SnapsToDevicePixels="True">
<Rectangle RadiusX="2"
RadiusY="2"
Fill="{TemplateBinding Panel.Background}" />
...
I've found the error I believe. It seems that even though the template was extracted from the build in version. There was some kind of error with the following trigger in the template:
<Trigger Property="ProgressBar.IsIndeterminate">
<Setter Property="Panel.Background"
TargetName="Animation">
<Setter.Value>
<SolidColorBrush>#80B5FFA9</SolidColorBrush>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>False</s:Boolean>
</Trigger.Value>
</Trigger>
As soon as I removed this trigger (which had no visible impact on the visuals) the template began to work.
Just to be sure. You are binding internal Rectangle to the Background property, while it's not set in the ProgressBar definition (only Foreground is there). Is that correct?
Related
I'm using Material Design library in XAML. I need to re-style some components because I'm using a particular textbox in which I have a clickable icon.
<StackPanel Orientation="Horizontal" Width="328" Grid.Column="0" Background="#3B3A3A">
<TextBox Style="{StaticResource Style}" materialDesign:HintAssist.Hint="Text" Width="300"
TextWrapping="Wrap" materialDesign:HintAssist.HelperText="Text1"/>
<Button Opacity="1" Padding="2,0,0,0"
Height="53.2"
Background="Transparent"
BorderBrush="Transparent"
Command="{x:Static materialDesign:DialogHost.OpenDialogCommand}"
CommandTarget="{Binding ElementName=DialogSelection}">
<materialDesign:PackIcon Kind="ArrowExpand"/>
</Button>
First of all I need to remove the background when the textbox isFocused, so in the style I did something like this:
<Style x:Key="Style" TargetType="TextBox" BasedOn="{StaticResource MaterialDesignFilledTextFieldTextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Width="328"
materialDesign:BottomDashedLineAdorner.Thickness="{TemplateBinding Margin}">
<TextBox x:Name="text" TextWrapping="WrapWithOverflow" FontSize="16" FontWeight="Regular" Foreground="White"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="#656565"/>
<Setter Property="Background" Value="#3b3a3a"/>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="#00B5CE"/>
<Setter Property="Background" Value="#656565"/>
<Setter Property="BorderThickness" Value="2"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The issue is that using this code for the style (with the control template) I don't have available the helper text. How can I combine the two things? (I mean my settings for the background when the textbox isFocused and a HelperText available?)
NB: If I don't modify the template and just setting the background it happens that the background when the textbox isFocused isn't as I want but the HelperText is visible
It does not work, because you overwrite the control template of the TextBox and omit most of it that is needed for it to work correctly. A control template defines the visual apprearance of a control, as well as the states and transitions between them. You cannot base a contol template on another as you can with styles. Creating a custom control template means:
Creating it from scratch with all the required states and parts or
Copying the base/default style and adapting it.
For standard WPF controls, you can find required parts and states in the documentation, e.g. for TextBox here. Omitting any of the required components will lead to unexpected behavior or broken visuals states. In case of Material Design, there are even more things necessary to make the controls work correctly, but they are not documented like on MSDN, so you have to create a copy of the default style and adapt it.
You can find the default styles for TextBox here on Github. In newer versions, the styles are renamed to MaterialDesignFilledTextBox because of this issue. The derived style hierarchy is as follows:
MaterialDesignTextBoxBase
MaterialDesignFloatingHintTextBox
MaterialDesignFloatingHintTextBox
MaterialDesignFilledTextFieldTextBox
The control template is defined in MaterialDesignTextBoxBase, which is the base style for all other styles. What you have to do now is to copy the MaterialDesignTextBoxBase style, give it a name and adapt the states as in your provided code. You can merge the setters of the three derived styles above into your custom style. Then you will have a custom style that incorporates all necessary states and parts that will work as you expect it.
You can't "combine" ControlTemplates. You must define a template as a whole.
This means that you should copy the default template in MaterialDesignFilledTextFieldTextBox that includes the helper text and then modify it as per your requirements, i.e. by adding a IsFocused trigger to it.
I am afraid you cannot base a template on another template or add triggers to a template that is defined elsewhere.
Is it possible to change the style of the red rectangle that appear when the AutoCompleteBox from the WPF Toolkit has an error? I successfully changed it on the TextBox just creating a new style for the control but no matter what I do with the AutoCompleteBox I can't get rid of that red rectangle. Even if I remove the style like this:
<input:AutocompleteBox Style="{x:Null}"/>
I cannot see the control but if I have an error on the control binding, it still shows a red line! What I would really like is that the AutoCompleteBox use the internal TextBox validation indicator but first I need to remove that outer rectangle. Any ideas on how to do this or what is creating that red rectangle?
AutocompleteBox consists of TextBox, SelectionAdapter, DropDownToggle and Popup.
And error-sate style, that you've described, is defined in TextBoxStyle:
<Style TargetType="controls:AutoCompleteBox">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:AutoCompleteBox">
<Grid Margin="{TemplateBinding Padding}"
Background="{TemplateBinding Background}">
<TextBox IsTabStop="True" x:Name="Text" Style="{TemplateBinding TextBoxStyle}" Margin="0" />
...
To change TextBox behavior when error - just change it's style.
We have a custom canvas which has specialized nodes that behave a lot like a standard MDI application's windows. The desired behavior is that if any of the child controls of the "window" have the focus, then that "window" is said to be active.
Now the IsFocused property doesn't seem to cascade, meaning if a child control has the focus, it's container is not also set to 'focused' so we can't use that. For the same reason, we can't set the IsFocused property on the container as I believe that would steal it from the child.
My only thought is to create a new DP called HasChildWithFocus or something like that, then in the code-behind, listen for the bubbled events and set that flag. Not sure that's the best way to go. (We may implement that as a combination attached property/attached behavior kinda thing.)
But of course it would be much better if we could simply ask a control 'Hey... do you or any of your children have the focus?'
So can you?
You can use UIElement.IsKeyboardFocusWithin directly like this:
<Grid>
<Grid.Resources>
<Style x:Key="panelStyle" TargetType="Border">
<Setter Property="BorderBrush" Value="PaleGoldenrod"/>
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="PaleGreen"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<UniformGrid Columns="2">
<Border BorderThickness="10" Style="{StaticResource panelStyle}">
<StackPanel>
<TextBox Text="TextBox1"/>
<TextBox Text="TextBox2"/>
</StackPanel>
</Border>
<Border BorderThickness="10" Style="{StaticResource panelStyle}">
<StackPanel>
<TextBox Text="TextBox3"/>
<TextBox Text="TextBox4"/>
</StackPanel>
</Border>
</UniformGrid>
</Grid>
In this example the border that contains the element with the keyboard focus is styled with a different border brush.
I have a problem styling/templating an AccordionItem in the accordion control from the silverlight toolkit. For some reason, the child controls are Horizontally Aligned Left. The only way I can get to fix this is to edit the ExpandableContentControlStyle on the AccordionItem.
The style is located below:
<Style x:Key="ExpandableContentControlStyle1" TargetType="layoutPrimitivesToolkit:ExpandableContentControl">
<Setter.Value>
<ControlTemplate TargetType="layoutPrimitivesToolkit:ExpandableContentControl">
<ContentPresenter x:Name="ContentSite" Cursor="{TemplateBinding Cursor}" Margin="0" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="Stretch" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now my problem is that to have this style being attached to the AccordionItem, I have to set it:
<layoutToolkit:Accordion HorizontalAlignment="Stretch">
<layoutToolkit:AccordionItem Header="Hello" BorderBrush="{x:Null}" ExpandableContentControlStyle="{StaticResource ExpandableContentControlStyle1}"/>
<layoutToolkit:AccordionItem Header="Haha" BorderBrush="{x:Null}"/>
</layoutToolkit:Accordion>
But those AccordionItem will be generated from an ItemSource. What I'd like to do is to have that style be applied to the generated AccordionItem without setting it.
PS. The above problem can become obsolete if I can just find out how to edit the (ContentPresenter x:Name="ContentSite") from the parent Accordion. I cannot edit it from none of the following template properties:
ContentTemplate
ItemContainerStyle
AccordionButtonStyle
ItemsPanel
ItemTemplate
If anyone knows what is going on with that, I'd appreciate the help or you can just help with styling of multiple elements.
I haven't used the Accordion control myself, though typically you set the ItemContainerStyle to the style you want for each item in the list. For instance, if you wanted a specific ListBoxItem style on a ListBox, you set the ItemContainerStyle to the ListBoxItem style you want. I glanced at the source for the Accordion and this seems to hold true for that control as well. Try setting the ItemContainerStyle property of the Accordion to your ExpandableContentControlStyle1.
<layoutToolkit:Accordion
HorizontalAlignment="Stretch"
ItemContainerStyle="{StaticResource ExpandableContentControlStyle1}">
</layoutToolkit:Accordion>
To set the style outside of the control itself, create a style for the Accordion. If you're using Silverlight 4, you can use implicit styles. Put the following style in the <UserControl.Resources> section of your page.
<Style TargetType="layoutToolkit:Accordion">
<Setter Property="ItemContainerStyle" Value="{StaticResource ExpandableContentControlStyle1}"/>
</Style>
Otherwise, with Silverlight 3 you'll have to explicitly give the style a Key and explicitly set the style on the Accordion control.
<Style x:Key="Control_Accordion" TargetType="layoutToolkit:Accordion">
<Setter Property="ItemContainerStyle" Value="{StaticResource ExpandableContentControlStyle1}"/>
</Style>
<layoutToolkit:Accordion
Style="{StaticResource Control_Accordion}"
HorizontalAlignment="Stretch">
</layoutToolkit:Accordion>
Please bear with me Silverlight Designer Gurus, this is compicated (to me).
I'm creating a custom control which derives form the Silverlight 3.0 ListBox. In an effort not to show tons of code (initially), let me describe the setup.
I have a class library containing a class for my control logic. Then I have a Themes/generic.xaml that holds the styling details. In generic.xaml, I have a style that defines the default layout and look for the ListBox where I'm setting a values for the Template, ItemsPanel and ItemTemplate.
In my test app, I add my control on to MainPage.xaml and run it and it works great. I dynamically bind data to my control and that works fine.
Now I want to set the ItemContainerStyle for my derived control. If I create a style in the MainPage.xaml file and set the ItemContainerStyle property to that control as in:
<dti:myControl x:Name="MyControl1" ItemContainerStyle="{StaticResource MyListBoxItem}"
Height="500"
Width="200"
Margin="10"
Background="AliceBlue"
/>
It works as expected.
However, I'd like to do this in the class library or, more specifically, in generic.xaml. I tried to this Setter to my current Style:
<Setter Property="ItemContainerStyle">
<Setter.Value>
<ControlTemplate>
<Grid Background="Red" Margin="3">
<ContentPresenter x:Name="contentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
HorizontalAlignment="Stretch" Margin="3"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
And it fails miserably with:
"System.ArgumentException: 'System.Windows.Controls.ControlTemplate' is not a valid value for property 'ItemContainerStyle'."
Note: This is not my actual style I'd like to use for ItemContainerStyle. I'm actually looking to plug in some VSM here for the various selected/unselected states of the a ListBoxItem (for a dynamically bound control).
So, to the question is how do I apply the ItemContainterStyle to my custom control when it's defined using generic.xaml? I do not want that property set when I actually use the control later on.
Thanks,
Beaudetious
You missed to put Style tag inside your Setter.Value. ItemContainerstyle explects a Style to ListBoxItem(Unless you subclassed ListBoxItem to your own derived version.)
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType=”{x:Type ListBoxItem}“ >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid Background="Red" Margin="3">
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="Stretch" Margin="3"/>
</Grid>
</ControlTemplate>
<Setter.Value>
</Style>
</Setter.Value>