How to write trigger to textbox IskeyboardFocused property - c#

I am trying to change other UI element visibility when textbox is focused. I think that isKeyboardFocused event may solve my problem. So i write my xaml as following.
<TextBox x:Name="SearchBox" Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch">
<i:Interaction.Triggers>
<e:PropertyChangedTrigger>
<i:Interaction.Behaviors>
<e:ConditionBehavior>
<e:ConditionalExpression>
<e:ComparisonCondition LeftOperand="{Binding SearchBox.IsKeyboardFocused}" Operator="Equal" RightOperand="rue" />
</e:ConditionalExpression>
</e:ConditionBehavior>
</i:Interaction.Behaviors>
<e:ChangePropertyAction TargetName="SearchLabel" PropertyName="Visibility" Value="Hidden" />
</e:PropertyChangedTrigger>
</i:Interaction.Triggers>
</TextBox>
<TextBlock x:Name="SearchLabel" Text="Search" FontStyle="Italic" Foreground="Gray" IsHitTestVisible="False" Visibility="Visible" />
This trigger is not working and i could'nt find the problem. What can i do to fix this problem or any other idea about it?

I would bind the Visibility to the IsKeyboardFocused property as follows:
<UserControl.Resources>
<YourNamespace:BoolToVisConverter x:Key="BoolToVis" />
</UserControl.Resources>
...
<TextBox x:Name="SearchBox" />
<Label Visibility="{Binding ElementName=SearchBox, Path=IsKeyboardFocused, Converter={StaticResource BoolToVis}, ConverterParameter='invert'}">hello</Label>
using a customized BoolToVisibilityConverter:
public class BoolToVisConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is bool)) throw new ArgumentException("bool value expected");
Visibility invisibleMode = (parameter == null || !(parameter is string) ||
!((string) parameter).ToLower().Contains("hidden"))
? Visibility.Collapsed
: Visibility.Hidden;
if ((parameter as string)?.ToLower().Contains("invert") ?? false) return (!(bool) value) ? Visibility.Visible : invisibleMode;
return ((bool) value) ? Visibility.Visible : invisibleMode;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
The Converter parses given CommandParameter string for:
- "invert": true --> invisible, false --> visible
- "hidden": invisble case leads to Visibilitys.Hidden, otherwise it's Visibility.Collapsed

Well, I also find another answer which solves my problem easily. It may be also useful who has the same problem like me.
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Search" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>

Related

Change predefined style inside a control in xaml

I have the following style in App.xaml:
<Style TargetType="{x:Type Button}">
<Style.Resources>
<DataTemplate x:Key="Unpressed">
<Image Stretch="Uniform" Source="Img/button1.png"/>
</DataTemplate>
<DataTemplate x:Key="Pressed">
<Image Stretch="Uniform" Source="Img/button1_press.png"/>
</DataTemplate>
</Style.Resources>
<Setter Property="ContentTemplate" Value="{StaticResource Unpressed}"/>
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource Pressed}"/>
</Trigger>
</Style.Triggers>
</Style>
I want to change the data template from my button, something like this:
<Button x:Name="Button2">
<Style>
<Style.Resources>
<DataTemplate x:Key="Unpressed">
<Image Stretch="Uniform" Source="../Img/button2.png"/>
</DataTemplate>
<DataTemplate x:Key="Pressed">
<Image Stretch="Uniform" Source="../Img/button2_press.png"/>
</DataTemplate>
</Style.Resources>
</Style>
</Button>
So basically, all my buttons have the same style but each button have an unique image, I need to change the DataTemplate of the style individually for each button
This is my proposed solution:
For the style:
<Application.Resources>
<local:ImgToDisplayConverter x:Key="ImgToDisplayConverter"/>
<local:ImgPressedToDisplayConverter x:Key="ImgPressedToDisplayConverter"/>
<Style TargetType="Image" x:Key="PressedButtonImageStyle">
<Setter Property="Source">
<Setter.Value>
<MultiBinding Converter="{StaticResource ImgToDisplayConverter}">
<Binding Path="Tag" RelativeSource="{RelativeSource AncestorType=Button}"/>
</MultiBinding>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsPressed, RelativeSource={RelativeSource AncestorType=Button}}" Value="true">
<Setter Property="Source">
<Setter.Value>
<MultiBinding Converter="{StaticResource ImgPressedToDisplayConverter}">
<Binding Path="Tag" RelativeSource="{RelativeSource AncestorType=Button}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Application.Resources>
For the Control:
<Button Tag="button1" Width="100" Height="100" HorizontalAlignment="Left">
<ContentControl>
<Image Stretch="Uniform" Style="{StaticResource PressedButtonImageStyle}" IsHitTestVisible="False"/>
</ContentControl>
</Button>
The Converters:
class ImgToDisplayConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
string image = values[0].ToString();
string resourceName = String.Format("pack://application:,,,/{0}.png", image);
return new BitmapImage(new Uri(resourceName));
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
class ImgPressedToDisplayConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
string image = values[0].ToString();
string resourceName = String.Format("pack://application:,,,/{0}_pressed.png", image);
return new BitmapImage(new Uri(resourceName));
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
You can change the code depending on your needs.
I use this simple code and it works well(if you want to release the button from being pressed ,set timer).I hope this will help you..
xaml code
<Button Name="male" Height="318" Width="352" Click="male_Click" Margin="236,120,1332,642">
<Button.Background>
<ImageBrush ImageSource="pack://application:,,,/Imagesrc/logotype/USER_MALE.png" ></ImageBrush>
</Button.Background>
</Button>
pressed code
public void male_Click(object sender, RoutedEventArgs e)
{
System.Windows.Controls.Image img = new System.Windows.Controls.Image();
img.Source = new BitmapImage(new Uri(#"pack://application:,,,/maindocket;component/Imagesrc/logotype/USER_MALE_SELECTED.png"));
male.Content = img;
}

Cant set Style in Trigger wpf

i want to change style when toggle button checked
<ToggleButton.Style>
<Style TargetType="ToggleButton" BasedOn="{StaticResource ToggleButtonPrimary}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ButtonNude, Path=IsChecked}" Value="True">
<Setter Property="Style" Value="{StaticResource ToggleButtonDanger}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
but my code not work and app crash
As suggested by #clemens , the right way would be to have template and apply in controlTemplate with TargetName
There is one more (may be ugly) way:
On view:
<StackPanel>
<StackPanel.Resources>
<local:Myconverter x:Key="MyConverter" />
<Style TargetType="ToggleButton" x:Key="ToggleButtonPrimary">
<Setter Property="Background" Value="blue" />
</Style>
<Style TargetType="ToggleButton" x:Key="ToggleButtonDanger">
<Setter Property="Background" Value="Red" />
</Style>
</StackPanel.Resources>
<CheckBox Margin="20" x:Name="chk" />
<ToggleButton Width="100" Height="100" >
<ToggleButton.Style>
<MultiBinding Converter="{StaticResource MyConverter}">
<MultiBinding.Bindings>
<Binding ElementName="chk" Path="IsChecked"/>
<Binding RelativeSource="{RelativeSource AncestorType=StackPanel}"/>
</MultiBinding.Bindings>
</MultiBinding>
</ToggleButton.Style>
</ToggleButton>
</StackPanel>
Converter:
public class Myconverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if ((bool)values[0])
{
return (values[1] as FrameworkElement).Resources["ToggleButtonDanger"];
}
else
return (values[1] as FrameworkElement).Resources["ToggleButtonPrimary"];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Hope that helps.

How to enable a specific button on a specific row of a datagrid

I would to like to enable a Button for a specific row of a DataGrid and disable it for the other rows in code behind. The thing is the IsEnabled property impact all the buttons in all the rows which is not what I want. It cannot have two different values (visible for some rows and Collapsed for others in the same time)
Can you help me please ?
here is my xaml :
<DataGrid ItemsSource="{Binding TaskUsers}" Name="DgUser" AutoGenerateColumns="False" IsReadOnly="True" SelectionUnit="FullRow" SelectionMode="Single" CanUserAddRows="False" CanUserSortColumns="False" SelectedValuePath="TaskUserId" >
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<Button BorderThickness="0" ToolTip="Subscribe" Click="AddTaskUser_OnClick">
<Image Source="/Sinergi;component/Images/add-icon16.png"/>
</Button>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button BorderThickness="0" ToolTip="Delete a User" Click="DeleteTaskUser_OnClick" Name="DeleteUserButton" Loaded="DeleteUserButton_OnLoaded">
<Image Source="/Sinergi;component/Images/Trash-can-icon16.png" />
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="UserName" Binding="{Binding User.Name}" />
</DataGrid.Columns>
here is my code behind code
private void DeleteUserButton_OnLoaded(object sender, RoutedEventArgs e)
{
var delete = sender as Button;
if (delete == null) return;
foreach (var item in DgUser.Items)
{
var o = (TaskUser) item;
if (o.UserId == Identity.This.OnBehalfOfUser.UserId) continue;
delete.IsEnabled = false;
delete.Visibility = Visibility.Collapsed;
}
}
You should bind the IsEnabled property of the Button to a property of your TaskUser object and get rid of the DeleteUserButton_OnLoaded event handler:
<DataTemplate>
<Button BorderThickness="0" ToolTip="Delete a User" Click="DeleteTaskUser_OnClick" Name="DeleteUserButton">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Style.Triggers>
<DataTrigger Binding="{Binding UserId}" Value="{x:Static local:Identity.This.OnBehalfOfUser.UserId}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Content>
<Image Source="/Sinergi;component/Images/Trash-can-icon16.png" />
</Button.Content>
</Button>
</DataTemplate>
You need to set the Value of the DataTrigger to whatever Identity.This.OnBehalfOfUser.UserId is, or use a value converter:
<DataTemplate>
<DataTemplate.Resources>
<local:Converter x:Key="converter" />
</DataTemplate.Resources>
<Button BorderThickness="0" ToolTip="Delete a User" Click="DeleteTaskUser_OnClick" Name="DeleteUserButton">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Style.Triggers>
<DataTrigger Binding="{Binding UserId, Converter={StaticResource converter}}" Value="False">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Content>
<Image Source="/Sinergi;component/Images/Trash-can-icon16.png" />
</Button.Content>
</Button>
</DataTemplate>
Converter:
class Converter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (int)value == Identity.This.OnBehalfOfUser.UserId;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}

Textbox placeholder translations WPF XAML

I have this XAML code that creates a txtbox with a placeholder text, that appears and disapears if it's focused or not.
But right now, I need to translate the aplication to 2 languages with a button. That button simply sets a global variable to "EN" for english and "ES" for spanish.
How can I adapte the code, so depending on that variable (written in code behind) the text "Please, write the reason for your request" changes?
This is the code working right now:
<TextBox x:Name="txt_reasons" ScrollViewer.VerticalScrollBarVisibility="Auto" HorizontalAlignment="Left" Height="74" Margin="82,247,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="344" TabIndex="4" MaxLength="150" TextChanged="txt_reasons_TextChanged" IsEnabled="False" IsHitTestVisible="True">
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Top" Stretch="None">
<VisualBrush.Visual>
<Label Content="Please, write the reason for your request" Foreground="Gray" ClipToBounds="True" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
You could use a Label Style with a DataTrigger that binds to the window property.
Please refer to the following sample code.
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
Title="MainWindow" Height="300" Width="300" x:Name="win">
<StackPanel>
<TextBox x:Name="txt_reasons" ScrollViewer.VerticalScrollBarVisibility="Auto" HorizontalAlignment="Left" Height="74" TextWrapping="Wrap" VerticalAlignment="Top" Width="344" TabIndex="4" MaxLength="150">
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Top" Stretch="None">
<VisualBrush.Visual>
<Label Foreground="Gray" ClipToBounds="True">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Content" Value="Please, write the reason for your request"/>
<Style.Triggers>
<DataTrigger Binding="{Binding TheLanguage, Source={x:Reference win}}" Value="ES">
<Setter Property="Content" Value="spanish..."/>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Button Content="Toggle Language" Click="Button_Click" />
</StackPanel>
</Window>
Code:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
}
private string _language = "EN";
public string TheLanguage
{
get { return _language; }
set { _language = value; NotifyPropertyChanged(); }
}
private void Button_Click(object sender, RoutedEventArgs e)
{
TheLanguage = TheLanguage == "EN" ? "ES" : "EN";
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Note that the window class must implement the INotifyPropertyChanged interface and raise the PropertyChanged event whenever the source property is set to a new value for the Label to get updated.

Datatrigger not firing when using a converter

I have a rectangle which I want to set 4 different icons to based on if a value inside my page.cs is between certain values, for instance:
If value is 0 show icon 1.
if value is larger than 0 but smaller or equal to 0.25 show icon 2.
If value is >0.25 && value is <=0.5 show icon 3.
If value is >0.5 && value is <=0.75, show icon 4.
and If value is >0.75 && value is <=1 show icon 5.
Here's what my variable looks like:
private double _double = 0.25;
public double Volume
{
get
{
return _double;
}
set
{
_double = value;
OnPropertyChanged("Volume");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
I also have INotifyPropertyChanged set next to the partial class
And here's the converter I'm using:
[ValueConversion(typeof(double), typeof(int))]
public class VolumePicture : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (System.Convert.ToDouble(value) <= 0.25)
{
return 1;
}
else if (System.Convert.ToDouble(value) > 0.25 && System.Convert.ToDouble(value) <= 0.5)
{
return 2;
}
else if (System.Convert.ToDouble(value) > 0.5 && System.Convert.ToDouble(value) <= 0.75)
{
return 3;
}
else if (System.Convert.ToDouble(value) > 0.75 && System.Convert.ToDouble(value) <= 1)
{
return 4;
}
else
{
return 0;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
It basically takes an input and does exactly how I described in the first part.
Aaaand here's the XAML I have for the rectangle which I want to change the opacitymask for:
<Rectangle Height="20" Margin="0,2,0,0">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="#FF929292" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=VolumeButton}"
Value="True">
<Setter Property="Fill" Value="White" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=NowPlaying.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource VolumePictureConverter}}" Value="5">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_mute}"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=NowPlaying.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ResourceKey=VolumePictureConverter}}" Value="1">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_0}"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=NowPlaying.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ResourceKey=VolumePictureConverter}}" Value="2">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_1}"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=NowPlaying.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ResourceKey=VolumePictureConverter}}" Value="3">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_2}"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=NowPlaying.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource ResourceKey=VolumePictureConverter}}" Value="4">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_3}"/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
This might look quite messy and for that, I'm sorry.
But, here's my problem: When I change the Volume variable during runtime, nothing seems to happen. I think it's the converter that's not firing, but I have NO idea why this is happening(!)
And since I'm really not that good with binding and converters and WPF in general, I've gotten stuck with this..
Anyone got an idea about what the troublemaker might be?
Thank you
One thing to note is that I didn't always have the "NowPlaying.Volume" path in there, I just tried a bunch of stuff.
And when I'm debugging I'm getting this in the output (which gets renamed to "Path error: 'Volume'" when I remove the Nowplaying.
System.Windows.Data Error: 40 : BindingExpression path error: 'NowPlaying' property not found on 'object' ''Rectangle' (Name='')'. BindingExpression:Path=NowPlaying.Volume; DataItem='Rectangle' (Name=''); target element is 'Rectangle' (Name=''); target property is 'NoTarget' (type 'Object')
It seems that you are binding to the Rectangle instead of it's DataContext. Rectangle doesn't have property Volume, hence you'll get binding error. Try to change your binding statement to something like this (notice this part : ...Path=DataContext.Volume...) :
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
.......
<Style.Triggers>
.......
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=DataContext.Volume, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource VolumePictureConverter}}"
Value="5">
<Setter Property="OpacityMask">
<Setter.Value>
<VisualBrush Visual="{StaticResource appbar_sound_mute}"/>
</Setter.Value>
</Setter>
</DataTrigger>
.......
</Style.Triggers>
.......
</Style>
</Rectangle.Style>

Categories