How to apply DataTrigger with ComboBox ItemContainerStyle in UWP? - xaml

I am trying to change the value of ComboBoxItem based on the property value assigned to the ComboBox ItemSource.
I know that in WPF it can be achieved as below:
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="Background" Value="#FFD2D2" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsValid}" Value="True">
<Setter Property="Background" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.ItemContainerStyle>
In UWP I tried using behaviors, but still, it's not working.
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="Background" Value="Transparent" />
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsValid}" Value="True">
<core:ChangePropertyAction PropertyName="Background" Value="{ThemeResource MyBorderBrush}" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Style>
</ComboBox.ItemContainerStyle>
I also tried to use VSM, but am not sure how to apply the conditional value.
<Style TargetType="ComboBoxItem">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Grid x:Name="LayoutRoot" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
// What should go here?
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
EDIT:
I would prefer a solution setting the background of ComboBoxItem itself, instead of creating separate Grid/Border and then using Converters for the background.

As far as I know, UWP xaml doesn't support such triggers in style. Generally, we use the Behavior datatrigger on the control's root child node. If you don't want to use the data binding as #touseefbsb's answer, but you want to change the ComboboxItem style base on your data model, I think you can try to operate the ComboBox's Itemtemplate and use the Behavior datatrigger in it.
<ComboBox Width="300" Height="60" Name="MyComBoBox" ItemsSource="{Binding models}">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid Name="MyGrid">
<TextBlock Text="{Binding Name}"></TextBlock>
<interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsValid}" ComparisonCondition="Equal" Value="true">
<core:ChangePropertyAction PropertyName="Background" TargetObject="{Binding ElementName=MyGrid}"
Value="{StaticResource MyColor}" />
</core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

This is how you bind a collection to a ComboBox in uwp, and set the background of each item with a property value of your collection items.
XAML
<ComboBox
x:Name="ComboBox1"
ItemsSource="{x:Bind Books}"
Header="Select A Book">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="models:Book">
<StackPanel
Background="{x:Bind MyBackground}"
Padding="8">
<TextBlock
Text="{x:Bind Title}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
C#
ObservableCollection<Book> Books = new ObservableCollection<Book>();
public MainPage()
{
this.InitializeComponent();
Books.Add(new Book("Book1",new SolidColorBrush(Colors.Red)));
Books.Add(new Book("Book2",new SolidColorBrush(Colors.Green)));
Books.Add(new Book("Book3",new SolidColorBrush(Colors.Blue)));
}
Models.Book
public class Book
{
public string Title {get; set;}
public SolidColorBrush MyBackground{get; set;}
public Book(string title,SolidColorBrush myBackground)
{
Title = title;
MyBackground = myBackground;
}
}
So Basically you just need to bind the background property of you Stackpanel in which you have wrapped the content of your ComboBoxItem you can wrap your content even in a Grid or a border as well whatever you prefer.

Related

Rounded corner for ToggleButton in UWP

<Style x:Key="tests" TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ToggleButton
Background="{Binding Background,
RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay}"
IsChecked="{Binding IsChecked,
RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay}"
Content="{Binding Content,
RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I am using above code to customize toggle button functionality, but i want to show the toggle button as rounded corner.
To get a toggle button with rounded corners you can do the following :
Right click on the button and select Edit Template > Create a copy
Give your style a name
Search for the Border template in the resource code and set the corner radius to 33 (CornerRadius="33")
Hope this helps..!
In recent versions of UWP, ToggleButton exposes a CornerRadius property (thanks #Clint Rutkas).
Otherwise:
<ToggleButton
Background="Transparent"
FontSize="16"
IsChecked="{Binding IsEnabled, Mode=TwoWay}"
IsTabStop="False"
ToolTipService.ToolTip="Press to enable/disable metronome (Space)">
<ToggleButton.KeyboardAccelerators>
<KeyboardAccelerator Key="Space" />
<KeyboardAccelerator Key="P" />
</ToggleButton.KeyboardAccelerators>
<ToggleButton.Resources>
<x:String x:Key="Play"></x:String>
<x:String x:Key="Stop"></x:String>
<Style TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Border
x:Name="border"
Width="56"
Height="56"
Padding="2"
Background="{TemplateBinding Background}"
BorderBrush="{ThemeResource ButtonBorderThemeBrush}"
BorderThickness="1"
CornerRadius="28">
<FontIcon x:Name="icon" Glyph="{StaticResource Play}" />
</Border>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<StateTrigger IsActive="{Binding IsEnabled}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="icon.Glyph" Value="{StaticResource Stop}" />
<Setter Target="icon.FontSize" Value="30" />
<Setter
Target="icon.Foreground"
Value="{ThemeResource SystemColorHighlightTextColor}" />
<Setter
Target="border.Background"
Value="{ThemeResource SystemColorHighlightColor}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToggleButton.Resources>
</ToggleButton>

UWP Xaml GridViewItem: Remove margin

I want to create a grid of images without any margin between them. I tried to achieve this through a GridView. If there is an easier way, please let me know.
I found this answers on StackOverflow:
https://stackoverflow.com/a/10492464
https://stackoverflow.com/a/23817931/5739170
And ended up with this code:
<Page.Resources>
<Style x:Key="MyGridViewItemStyle" TargetType="GridViewItem">
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="0" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<GridViewItemPresenter ContentMargin="0" Padding="0" Margin="0" BorderThickness="0"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<GridView ItemsSource="{x:Bind FieldList}" Margin="0,50,0,0" Padding="0" BorderThickness="0" ItemContainerStyle="{StaticResource MyGridViewItemStyle}" IsItemClickEnabled="True" ItemClick="OnItemClick">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Field">
<Image Width="20" Height="20" Margin="0" Source="{x:Bind ImagePath}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<TextBlock x:Name="text">Hallo!</TextBlock>
</StackPanel>
</Grid>
But there is still a margin left:
Screenshot
I have also tried to use negative margins but when I use them clicks aren't recognized correctly anymore.
How can I remove the margins?
Seems like the GridViewItem has a default MinWidth of 44px.
You can set it to 0 via your GridViewItemStyle:
<Setter Property="MinWidth" Value="0" />
EDIT: it also has a default MinHeight, you might want to set that to 0 as well.
The code below should work:
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="0"/>
</Style>
</GridView.ItemContainerStyle>
Your code is good. If you add a Grid in the DataTemplate (with a Background), you will see there is no margin between grids :
<DataTemplate x:DataType="data:Field">
<Grid Background="Red">
<Image Width="20" Height="20" Margin="0" Source="{x:Bind ImagePath}"/>
</Grid>
</DataTemplate>
Your problem is the following : you set a fixed size for Image control wich all of them is in a container, but the container doesn't have a fixed, so images are centered in the container.
I see two solutions. First is to remove the fixed size for Image control and use Strecth property to fill correctly :
<DataTemplate x:DataType="data:Field">
<Image VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Stretch="UniformToFill"
Margin="0"
Source="{x:Bind ImagePath}"/>
</DataTemplate>
For the first solution, you must be sure of the filling behavior of the container. You can do something like :
<GridViewItemPresenter ContentMargin="0"
Padding="0"
Margin="0"
BorderThickness="0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch" />
The second solution is to set a fixed size on the container directly :
<Style x:Key="MyGridViewItemStyle"
TargetType="GridViewItem">
<Setter Property="Padding"
Value="0" />
<Setter Property="Margin"
Value="0" />
<Setter Property="BorderThickness"
Value="0" />
<Setter Property="Width"
Value="20" />
<Setter Property="Height"
Value="20" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<GridViewItemPresenter ContentMargin="0"
Padding="0"
Margin="0"
BorderThickness="0"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Add Xaml hyperlink to rectangle

I am trying to add a hyperlink to a xaml rectangle and it's not working. I tried adding hyperlink with a button and it works. How can I add hyperlink to a group of rectangle for the code below.
How to give Hyperlink for below Code
<Rectangle Fill="Red" HorizontalAlignment="Left" Height="38" Margin="1038,74,0,0" Stroke="Black" VerticalAlignment="Top" Width="426"/>
<TextBlock HorizontalAlignment="Left" Margin="1173,82,0,0" TextWrapping="Wrap" Text="Pending Sites " VerticalAlignment="Top" Height="24" Width="142" Foreground="#FFF7F6F1" FontSize="20" RenderTransformOrigin="0.5,0.5" UseLayoutRounding="False" d:LayoutRounding="Auto">
<TextBlock.RenderTransform>
<CompositeTransform Rotation="-0.098"/>
</TextBlock.RenderTransform>
</TextBlock>
Code I tried with Button which is working fine
<Button Content="Click to go to desc page" Click="Button_Click_1" Margin="62,376,0,357"/>
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.Frame.Navigate(typeof(dPlanner2x.MyPageDetails));
}
Rather than trying to turn a Rectangle into a click-able object, you are much better off if you apply a Style to a Button.
An example of a Style to change the look of a Button is given below:
<Style x:Key="btnCommand" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="rct"
TextBlock.Foreground="White"
Background="DarkGray"
BorderBrush="DarkGray"
BorderThickness="1"
Cursor="Hand"
UseLayoutRounding="True"
SnapsToDevicePixels="True"
Margin="10"
Height="24"
MinWidth="75">
<ContentPresenter TextBlock.FontStyle="Segoe UI Semibold"
TextBlock.FontSize="14"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="rct"
Property="TextBlock.Foreground"
Value="DarkGray" />
<Setter TargetName="rct"
Property="Background"
Value="LightGray" />
<Setter TargetName="rct"
Property="BorderBrush"
Value="DarkGray" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="rct"
Property="TextBlock.Foreground"
Value="DarkGray" />
<Setter TargetName="rct"
Property="Background"
Value="White" />
<Setter TargetName="rct"
Property="BorderBrush"
Value="LightGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Obviously, you will want something that looks completely different, but the Style template above can be easily modified to fit your needs.

How to stop style overwriting in wpf?

I create a WPF UserContorl and create a style for ListView in my UserContorl theme.
My ListView Style :
<Style TargetType="ListView" x:Key="ReminderListView">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<CheckBox Style="{StaticResource ReminderCheckBox}" IsChecked="{Binding IsSelected, Mode=TwoWay}" Content="{Binding Title, Mode=OneTime}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
My ListView Style Work Correctly in UserContorl.
My used Xaml in UserControl:
<ListView Name="snoozeListView" Grid.Column="1" Style="{StaticResource ReminderListView}" ItemsSource="{Binding ReminderItems}" >
i use this UserControl in other WPF project which have a ListViewItem Style.
ListViewItem Style :
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Foreground" Value="{StaticResource ForegroundBrush}"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Padding" Value="2,0,2,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel SnapsToDevicePixels="True" Margin="2,0,2,0">
<Grid x:Name="Grid" Background="Transparent">
<Rectangle x:Name="SelectedRect" IsHitTestVisible="False" Fill="{StaticResource SelectedBackgroundBrush}" Opacity="0"/>
<GridViewRowPresenter Height="Auto" Margin="2"/>
</Grid>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now ListViewItem style overwriting the ListView ItemTemplate Style which defined in user control theme.
How can i stop overwriting.

How to use a template for TextBox of WPF 2010

I have a template written in xaml. Can you write how a template is turned on for TextBox?
<Grid.Resources>
<Storyboard x:Key="FlashErrorIcon">
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Hidden}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:03.2000000" Value="{x:Static Visibility.Visible}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:01" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="Background" Value="Pink"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True"
ToolTip="{Binding ElementName=controlWithError,Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
<Ellipse DockPanel.Dock="Right"
ToolTip="{Binding ElementName=controlWithError,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
Width="15" Height="15"
Margin="-25,0,0,0"
StrokeThickness="1" Fill="IndianRed" >
<Ellipse.Stroke>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFFA0404" Offset="0"/>
<GradientStop Color="#FFC9C7C7" Offset="1"/>
</LinearGradientBrush>
</Ellipse.Stroke>
<Ellipse.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource FlashErrorIcon}"/>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
<TextBlock DockPanel.Dock="Right"
ToolTip="{Binding ElementName=controlWithError,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
Foreground="White"
FontSize="10"
Margin="-15,5,0,0" FontWeight="Bold">!
<TextBlock.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource FlashErrorIcon}"/>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder Name="controlWithError"/>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
I tried to include in TextBox different ways, but I didn't manage to do it. How to include this template?
<TextBox>?????????What should I write here???????????>
?????????What should I write here???????????
</TextBox>
How to turn on the template? Any help will be appreciated!
You forgot to add the key textBoxInError to your TextBox style:
<Grid.Resources>
...
<Style x:Key="textBoxInError" TargetType="{x:Type TextBox}">
...
</Style>
...
</Grid.Resources>
Without that key the Style is handled as default style for TextBox. In that case you would not explicitly reference a Style in your TextBox declaration, and would have to remove the Style="{StaticResource textBoxInError}" part.
EDIT: If your Style is contained in a resource dictionary (like Grid.Resources in your XAML) and has a Key as shown above (textBoxInError), you would use that Style like this:
<Grid>
<Grid.Resources>
<Style x:Key="textBoxInError" TargetType="{x:Type TextBox}">
...
</Style>
...
</Grid.Resources>
...
<TextBox Style="{StaticResource textBoxInError}" ... />
</Grid>
You style has the following deceleration:
This means this style will be applied to all textboxs. Unless you set a different style yourself.
When you write this:
<TextBox Validation.ErrorTemplate="{StaticResource FlashErrorIcon}"
Style="{StaticResource textBoxInError}" TabIndex="1" Margin="147,145,168,131">
You're changing the default style (to the one named textboxInError ) ...
So just remove the Style attribute from the textbox.
Another Solution
If you want to give the style a specific name and not make it the default style, use:
<Style TargetType="{x:Type TextBox}" x:Key="textBoxInError" >
And then your original code will work correctly
e.g.
<TextBox Style="{StaticResource textBoxInError}" />