I've been using Converters to dynamically change stylings of my App depending on some conditions.
I found that the Converters does not always work properly.
Specifically, I found several instances where it was not working:
Using Converter with Value
<Style x:Key="Style_TextBlock_Label_H4"
BasedOn="{StaticResource Style_TextBlock_LabelBase}"
TargetType="TextBlock">
<Setter Property="FontSize" Value="{Binding Converter={StaticResource MyConverter},
ConverterParameter=LabelH4}" />
<Setter Property="Foreground" Value="#FFAAAAAA" />
</Style>
Using Converter with Style of ContentControl
<ContentControl Style="{Binding Converter={StaticResource LargeSizeConverter}, ConverterParameter=Style_ContentControl_Modifier_Radio_Minimal}">
<i:Interaction.Behaviors>
<Dovetail_UI_Register_Controls_Behaviors:PointerPressedToToggleBehaviorMinimal />
</i:Interaction.Behaviors>
</ContentControl>
For these 2 instances, so far they are not even entering the Converter itself.
The Converter works fine if used with TextBlock styling though:
<TextBlock x:Name="TextBlock_ControlPrimaryContent_Popoutright"
Style="{Binding Converter={StaticResource LargeSizeConverter},ConverterParameter=Style_Button_ModifierPopoutRight_Minimal}"
Text="">
Any idea if I'm doing something wrong / better way of doing things? Or if this is not supported at all?
Thank you!
Bindings in Style Setters are not supported in UWP/Store Apps.
Related
I'm trying out styles in avalonia and most works, except for pseudoclasses, they just get ignored.
I have created a window and all styles are in there and I have created a user control (with a button on - the pseudoclasses are on the button), using the styles. I do not use code, only xaml to define the styles.
I have tried it out in the "Style Selector" for the button as "Button:pseudoclassname" and "Button.le:pseudoclassname". I have also tried "Button:pointerover" and "Button:hover" as the documentation mentions that that could be modified. No result. The styles for the pseudoclasses are all ignored, the others are all executed correct.
Is there something I'm doing wrong or is this a bug in avalonia ?
The xaml windows file:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:Hub.Views"
xmlns:vm="using:Hub.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Hub.Views.MainWindow"
Icon="/Assets/avalonia-logo.ico"
Width="200" Height="300"
Title="Hub"
Classes="le">
<Window.Styles>
<Style Selector="Window.le">
<Setter Property="Background" Value="#191919"/>
</Style>
<Style Selector="Button.le">
<Setter Property="Background" Value="green"/>
<Setter Property="Foreground" Value="white"/>
</Style>
<Style Selector="Button.le:pointerover">
<Setter Property="Background" Value="red"/>
<Setter Property="Foreground" Value="white"/>
</Style>
<Style Selector="Button.le:pressed">
<Setter Property="Background" Value="blue"/>
<Setter Property="Foreground" Value="white"/>
</Style>
<Style Selector="TextBlock.le_update">
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="FontSize" Value="17"/>
<Setter Property="FontFamily" Value="Arial, Verdana"/>
<Setter Property="Foreground" Value="white"/>
<Setter Property="Background" Value="transparent"/>
</Style>
</Window.Styles>
<views:UpdateView/>
</Window>
The xaml user control file:
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Hub.Views.UpdateView">
<DockPanel>
<StackPanel DockPanel.Dock="Bottom">
<Button Classes="le" HorizontalAlignment="Center" HorizontalContentAlignment="Center" Width="300">
Check for updates
</Button>
</StackPanel>
<StackPanel Spacing="5" Margin="5">
<TextBlock Classes="le_update" HorizontalAlignment="Center" Margin="4">
No updates for Hub.
</TextBlock>
<TextBlock Classes="le_update" HorizontalAlignment="Center" Margin="4">
No updates for Engine.
</TextBlock>
</StackPanel>
</DockPanel>
</UserControl>
Button's Background property does get affected by your style, but at that point it has no effect on the actual Button's background, because Background property controls only the normal state of the button.
If you take a look at the default Button style here you can see that it passes its background to ContentPresenter via TemplateBinding:
<Setter Property="Template">
<ControlTemplate>
<ContentPresenter x:Name="PART_ContentPresenter"
Background="{TemplateBinding Background}"
but overrides ContentPresenter's background in a style like this:
<Style Selector="Button:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPointerOver}" />
Since it's ContentPresenter that actually draws the background (Button is a lookless control), you'll see the button to have ButtonBackgroundPointerOver and not the Button's Background property value.
So, you need to write a style that changes the inner ContentPresenter like this:
<Style Selector="Button.le:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="green" />
</Style>
Unfortunately that makes your styles theme-dependent since control templates are different between default and fluent themes.
The answer Kekekeks gave is the correct one for the question I asked.
However, I use this space in the hope to help novice users of avalonia with no background in xaml at all, like I do. Most of us look at avalonia to give our apps an interface that works on Windows/Mac/Linux. To be honest, at the moment of writing, no real alternatives in c# exist.
At this moment Avalonia does have examples and some documentation that is good, but not so for people not really having a background in xaml.
Therefore, go to Udemy or LikedIn.Learning or Youtube or wherever you find a good course on WPF AND AFTER THAT go to the documentation of Avalonia and start playing around.
The similarities that both (Avalonia and WPF) share is enormous !!! And yes it is mentioned a few times in the docs, but a blunt "Do go and learn WPF first if you are new to xaml !" on the frontpage of the documentation would have saved me a fair share of time in trying to find it all out via the website.
Fair is fair, the project still is in beta and the website is already well documented for that stage, so no blame to the team !
I would like to build a validation text box, which would be a normal UWP TextBox wrapped within a StackPanel, which also contains a TextBlock. The intent is that a validation message can be shown beneath the text box when there is a validation error.
I know I can do this by creating a custom control, but this would require me to implement all the properties I need and create a bunch of dependency properties, etc.
I'm hoping there is an easier way, where I can just completely derive the text box, but override the display template for it and include a label beneath it.
You can get most of the way there in XAML using the built-in IDataErrorInfo-based validation machinery and defining a control template for the TextBox's Validation.ErrorTemplate. There's a pretty good article at this link:
The XAML from the article at the link above follows, also check out this discussion on WPF's built-in validation here.
<Style TargetType="{x:Type Label}">
<Setter Property="Margin" Value="5,0,5,0" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="0,2,40,2" />
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="true">
<Border Background="OrangeRed" DockPanel.Dock="right" Margin="5,0,0,0"
Width="20" Height="20" CornerRadius="5"
ToolTip="{Binding ElementName=customAdorner,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center"
FontWeight="Bold" Foreground="white" />
</Border>
<AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
<Border BorderBrush="red" BorderThickness="1" />
</AdornedElementPlaceholder>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I'd like to have page headers in my app with either an icon or text centered in a 50px high bar at the top of the page. Optionally with a back-button.
For this reason I use a UserControl on each page which gets either one of those styles applied: PageHeaderStyle or PageHeaderBackStyle.
My implementation of one of those is the following (style definition in my App.xaml):
<Style x:Key="PageHeaderBaseStyle" TargetType="UserControl">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Height" Value="50" />
<Setter Property="Width" Value="NaN" />
<Setter Property="Background" Value="{StaticResource CDColor}" />
</Style>
<Style x:Key="PageHeaderStyle" TargetType="UserControl" BasedOn="{StaticResource PageHeaderBaseStyle}">
<Setter Property="Content">
<Setter.Value>
<Grid Background="{StaticResource CDColor}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" DataContext="{StaticResource MainPageModel}">
<TextBlock Style="{StaticResource PageHeaderTextBlockStyle}" Text="{Binding Title}" Visibility="{Binding TitleVisibility}" />
<Image Style="{StaticResource PageHeaderIconStyle}" Source="{Binding Icon}" Visibility="{Binding IconVisibility}" />
</Grid>
</Setter.Value>
</Setter>
</Style>
Applied like it should be:
<UserControl Style="{StaticResource PageHeaderStyle}" />
Now first I had used "Template" and applied a DataTemplate with the grid component. But this didn't work. Then I changed it to directly set the Content of the UserControl. This does work: After building the designer shows the page header (before it showed only the blue selection border, but no content - it was transparent).
But as soon as I start debugging the app on the emulator it disappears and the running app only shows a blank spot where it should be.
Why is this so? I mean after all the designer already shows it, why does it disappear then, though?
FYI: I do not get any binding exceptions nor any other. It just doesn't show up.
PS: I tried setting the Background in the base style while setting the grid's background to transparent. This didn't work either - only a blank spot.
Solved the problem: Best approach is probably to use a ContentControl. Using the Content property did not work, though. You have to use the ContentTemplate property. Using that one does work just fine.
I would like to be able to create a custom pivot page title style in my application, so that I may use it across multiple pages. Essentially I just want the title of the Pivot to be centered with a certain font size and type. Originally I was using an Image for my title but I really need a text title instead. How might I go about doing this? I've already tried setting this within App.xaml and using it within my MainPage.xaml but so far I don't have anything working.
App.xaml (original)
<Style x:Key="ApplicationName" TargetType="Image">
<Setter Property="Height" Value="50"/>
<Setter Property="Width" Value="92.85"/>
<Setter Property="Margin" Value="-3,0,0,0"/>
<Setter Property="Source" Value="/Assets/ApplicationTitle.png"/>
</Style>
MainPage.xaml
<phone:Pivot x:Name="mainPagePivotControl" Style="{StaticResource PivotStyle}">
<phone:Pivot.TitleTemplate>
<DataTemplate>
<Image Style="{StaticResource ApplicationName}"/>
</DataTemplate>
</phone:Pivot.TitleTemplate>
...
</phone:Pivot>
In reading a post about TreeView and binding to a view model (http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx), it seems that binding a TreeViewItem IsSelected property is possible. However, I have the following code which always fails on Initialize() because it's trying to set a read-only property?
<sdk:TreeView Grid.Column="0" Grid.Row="2" Style="{StaticResource TreeViewStyle}"
ItemsSource="{Binding tvData}" >
<sdk:TreeView.ItemContainerStyle>
<Style TargetType="sdk:TreeViewItem">
<Setter Property="IsEnabled" Value="True" />
<Setter Property="IsExpanded" Value="True" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</sdk:TreeView.ItemContainerStyle>
<sdk:TreeView.ItemTemplate>
<sdk:HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ItemName}" FontWeight="{Binding ItemFontWeight}"/>
</StackPanel>
</sdk:HierarchicalDataTemplate>
</sdk:TreeView.ItemTemplate>
You can't assign a binding via a Setter in a Style. Effectively what you are doing there is attempting to set a binding on the Setter.Value property. Xaml doesn't infer that you mean to set a binding on the target property. In turn the Setter just assumes you are trying to set a value directly to IsSelected which it knows is read only hence the error.
I can recommend this technique for getting around the problem:
http://blogs.msdn.com/b/delay/archive/2009/05/07/one-more-platform-difference-more-or-less-tamed-settervaluebindinghelper-makes-silverlight-setters-better.aspx
EDIT:
I should mention that I have not tried the technique for this exact scenario (binding the IsSelected property of a TreeViewItem), but I have used it on numerous other occasions, and so far it has worked flawlessly.