Setting focus in WPF with MVVM - c#

I have Grid with multiple Textboxes. Depending on actions the user might take focus should be changed to one of the textboxes. My current solution uses a string property in the ViewModel and a data trigger in xaml to change focus. It works nicely but it seems a rather roundabout way to achieve this so I was wondering if it could be done in a clearner way?
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding FocusedItem}" Value="number">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=number}"/>
</DataTrigger>
<DataTrigger Binding="{Binding FocusedItem}" Value="name">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=name}"/>
</DataTrigger>
<DataTrigger Binding="{Binding FocusedItem}" Value="id">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=id}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
As you can see the value of the property and the name of the element is the same so I would like to do this i a single trigger instead of having one trigger per element.
Maybe someone can come up with a cleaner way?
Thanks in advance

The way I handled setting focus in one of my projects was by using a focus extension (I apologize I do not remember where I saw the original post this is from).
public static class FocusExtension
{
public static bool GetIsFocused(DependencyObject obj)
{
return (bool)obj.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(DependencyObject obj, bool value)
{
obj.SetValue(IsFocusedProperty, value);
}
public static readonly DependencyProperty IsFocusedProperty =
DependencyProperty.RegisterAttached(
"IsFocused", typeof(bool), typeof(FocusExtension),
new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));
private static void OnIsFocusedPropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var uie = (UIElement)d;
if ((bool)e.NewValue)
{
uie.Focus();
}
}
}
And then in xaml file I use it as a Dependency Property:
<TextBox Uid="TB1" FontSize="13" localExtensions:FocusExtension.IsFocused="{Binding Path=TB1Focus}" Height="24" HorizontalAlignment="Left" Margin="113,56,0,0" Name="TB_UserName" VerticalAlignment="Top" Width="165" Text="{Binding Path=TB1Value, UpdateSourceTrigger=PropertyChanged}" />
You can then use a binding to set the focus.

Related

Change the value of a custom Dependency Property programmatically

I want to change the value of a custom Dependency Property programmatically.
This is my XAML:
<Window.Resources>
<ResourceDictionary>
<Style
x:Key="TreeViewItemStyle"
TargetType="TreeViewItem">
<Style.Triggers>
<Trigger
Property="local:ColorHelper.IsColor"
Value="True" >
<Setter
Property="Foreground"
Value="{Binding Color}" />
</Trigger>
<Trigger
Property="local:ColorHelper.IsColor"
Value="False" >
<Setter
Property="Foreground"
Value="Black" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</Window.Resources>
I want this style to be applied to a treeview
<TreeView
HorizontalAlignment="Stretch"
Margin="15,65,15,0"
x:Name="treeView1"
VerticalAlignment="Stretch"
ItemContainerStyle="{StaticResource TreeViewItemStyle}"
ItemTemplate="{StaticResource CheckBoxItemTemplate}"
Grid.ColumnSpan="1"
Grid.RowSpan="2"
Grid.Column="1" />
And changing the color value of the IsColor property through a checkbox:
<CheckBox
Name="CHK_Gray"
VerticalAlignment="Center"
Foreground="DarkGray"
Grid.Row="6"
Grid.Column="0"
Grid.RowSpan="1"
Grid.ColumnSpan="2"
Unchecked="grayCheckBox_Unchecked"
Checked="grayCheckBox_Checked">
Show Created Assembly (in Grey)
</CheckBox>
The Dependency Property is created like this:
public class ColorHelper : DependencyObject
{
public static readonly DependencyProperty IsColorProperty = DependencyProperty.Register(
"IsColor", typeof(bool), typeof(ColorHelper), new PropertyMetadata(false));
public static void SetIsColor(DependencyObject target, Boolean value)
{
target.SetValue(IsColorProperty, value);
}
public static bool GetIsColor(DependencyObject target)
{
return (bool)target.GetValue(IsColorProperty);
}
}
How can i do in the Checked and Unchecked event to change the value of the IsColor property?
private void grayCheckBox_Checked(object sender, RoutedEventArgs e)
{
???
}
private void grayCheckBox_Unchecked(object sender, RoutedEventArgs e)
{
???
}
Thank you very much for your help!
You need to get a reference to the element of which you want to set the attached property to begin with.
You could try this method to get the TreeViewItem elements of the TreeView and then set the property of all of them if that's that you want:
foreach(TreeViewItem tvi i tv.FindTreeViewItems())
ColorHelper.SetIsColor(tvi, true);
Note that you cannot edit the template programmatically. And even if you could, it wouldn't really help as it has already been applied to the actual elements.

WPF: How to make styles in XAML conditional on a variable in your own C# code

WPF and XAML newbie here....
I need to tie a WPF Trigger or DataTrigger in XAML code into some C# code in a class other than the class of the XAML control. This is very frustrating as all 28,000 tutorials I've read only give a trivial example for Trigger or DataTrigger that involves properties that already exist (e.g. MouseOver), none of them give examples of how to tie it in with your own C# code.
I have a screen for displaying various report types. The XAML for all of the report types is the same, except that for diagnostic reports, my requirements are that the DataGrid cells be configured with TextBlock.TextAlignment="Left", while all other reports (i.e. the default) should be TextBlock.TextAlignment="Center". (There are a few other differences; for brevity I'll just say that's the only difference.) I really don't want to have to duplicate the entire XAML to special-case the diagnostics report, since 99% of it would be the same as the other reports.
To use a Trigger, I thought perhaps I need my class to inherit from DependencyObject so I can define DependencyProperty's in it (being a WPF newbie I realize I may be saying some really outlandish things). So in my C# code, I have a class with this...
namespace MyApplication
{
public enum SelectedReportType
{
EquipSummary,
EventSummary,
UserSummary,
DiagSummary
}
public sealed class ReportSettingsData : DependencyObject
{
private static ReportSettingsData _instance; // singleton
static ReportSettingsData() { new ReportSettingsData(); }
private ReportSettingsData() // private because it's a singleton
{
if (_instance == null) // only true when called via the static constructor
_instance = this; // set here instead of the static constructor so it's available immediately
SelectedReport = SelectedReportType.EquipSummary; // set the initial/default report type
}
public static ReportSettingsData Instance
{
get { return _instance; }
}
public static SelectedReportType SelectedReport
{
get { return (SelectedReportType)Instance.GetValue(SelectedReportProperty); }
set { Instance.SetValue(SelectedReportProperty, value); }
}
public static readonly DependencyProperty SelectedReportProperty =
DependencyProperty.Register("SelectedReport", typeof(SelectedReportType), typeof(ReportSettingsData));
}
}
So in my XAML file, I've played with various incantations of Trigger and DataTrigger and can't figure out how to make it work. In every case, the diagnostic report has the same default characteristics of the other reports.
<my:HeaderVisual x:Class="MyApplication.ReportsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:MyApplication">
<DataGrid Name="_dgReport"
ColumnWidth="Auto"
CanUserAddRows="False"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"
ItemsSource="{Binding}"
IsReadOnly="True">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<Setter Property="TextBlock.TextAlignment" Value="Center"></Setter>
<Style.Triggers>
<!-- Override some property settings for Diagnostics reports... -->
<!--
<DataTrigger Binding="{Binding my:ReportSettingsData.SelectedReport}" Value="DiagSummary">
<DataTrigger Binding="{Binding Path=my:ReportSettingsData.SelectedReport}" Value="DiagSummary">
-->
<Trigger Property="my:ReportSettingsData.SelectedReport" Value="DiagSummary">
<Setter Property="TextBlock.TextAlignment" Value="Left"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
</my:HeaderVisual>
How can I get my Trigger to fire when ReportSettingsData.SelectedReport == SelectedReportType.DiagSummary?
How to make styles in XAML conditional on a variable in your own C# code
I recommend that you look into a CellTemplate Selector (GridViewColumn.CellTemplateSelector Property (System.Windows.Controls)) where you can do the selection logic in code behind.
Rough Example
Simply define the templates (4 but two shown) needed in the resource
<Window.Resources>
<DataTemplate x:Key="EquipTemplate">
<TextBlock Margin="2" Text="Equip" Foreground="Green"/>
</DataTemplate>
<DataTemplate x:Key="EventTemplate">
<TextBlock Margin="2" Text="Event" Foreground="Red"/>
</DataTemplate>
<DataTemplate x:Key="UserTemplate" ...
</Window.Resources>
Xaml template usage selector for the grid cell
<DataGridTemplateColumn Header="My Event">
<DataGridTemplateColumn.CellTemplateSelector>
<local:SelectedReportTypeTemplateSelector
EquipTemplate="{StaticResource EquipTemplate}"
EventTemplate="{StaticResource EventTemplate}"
User...
/>
</DataGridTemplateColumn.CellTemplateSelector>
</DataGridTemplateColumn>
Code Behind
public class MeetingTemplateSelector : DataTemplateSelector
{
public DataTemplate EquipTemplate { get; set; }
public DataTemplate EventTemplate { get; set; }
public DataTemplate UserTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item,
DependencyObject container)
{
DataTemplate result;
switch( ((ReportSettingsData) item).SelectedReport)
{
case EquipSummary : result = EquipTemplate; break;
case EventSummary : result = EventTemplate; break;
case UserSummary ..
}
return result;
}
}
Update
As per the comment that the variety of choices makes the template suggestion grow to over 30 templates. One other way might be to extend the target class with operational properties in lieu of the triggered actions. For example say we need a red color shown, provide it on the instance and bind.
public Partial MyClassInstance
{
public Brush ColorMeAs
{
get { return this.IsValid ? BrushGreen : BrushRed; }
}
... other properties as such:
}
then bind as such
Foreground="{Binding ColorMeAs}"
Triggers
Here is an example of a data trigger pulled from my archive:
<Style x:Key="LabelStyle" TargetType="{x:Type Label}">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="Width" Value="80" />
<Setter Property="Height" Value="28"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=LoginInProcess}" Value="True">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=LoginInProcess}" Value="False">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
Your C# code looks fine, and you already have the XML NameSpace declaration referencing your MyApplication namespace, so:
You should just be able to access the enum value using the x:Static markup using the enum identifier as shown in this example (I like this example because it also shows how to use non-custom x:Static and how to do some tree traversal as well):
<DataTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True" />
<Condition Binding="{Binding Type}" Value="{x:Static loc:AppProfileItemType.Custom}" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter TargetName="PART_Delete" Property="Visibility" Value="{x:Static Visibility.Visible}" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</DataTemplate.Triggers>
In your case your Markup for your enum should be:
Value="{x:Static my:SelectedReportType.DiagSummary}"

Structure of WPF DataGrid - change cells depending on value

I did bind an Object to a DataGridTextColumn and would like to reference one of its properties from within the corresponding CellStyle. I assumed that each cell of this column would contain an instance of MyObject. However I can't find a reference to the Object from within the DataGridCell (I used a trivial converter to set a break point and searched the DataGridCell-object for quite a while).
I am looking for the Property MyObject.IsEnabled and would like to reference that in the Path-Property noted with ??? in the code below. Any suggestions?
<DataGridTextColumn Binding="{Binding MyObject}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Path="???" Binding="{Binding RelativeSource={RelativeSource Self}, PresentationTraceSources.TraceLevel=High,Converter={StaticResource debugger}}" Value="False">
<!-- some setters -->
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
EDIT:
Since i want to apply this style to all Cells of my DataGrid later on it is essential to find the object which is bound to the cell via RelativeSource instead of adding a hardcoded binding to MyObject.
SOLUTION
Thanks to the input of antiocol i was able to find a solution for my case which possibly can be adapted to similar problems.
Since the problem is that we don't have access to the values of the Cell or a CellModel from within the CellStyle, we use an attached Property on the DataGridCell to store the whole CellModel in there. From there we can bind any accessible Property of the DataGridCell to any Property of our CellModel.
code for attached property:
public static class DataGridUtils
{
public static CellModel GetCellModel(DependencyObject obj)
{
return (CellModel)obj.GetValue(CellModelProperty);
}
public static void SetCellModel(DependencyObject obj, CellModel value)
{
obj.SetValue(CellModelProperty, value);
}
public static readonly DependencyProperty CellModelProperty =
DependencyProperty.RegisterAttached("CellModel", typeof(CellModel), typeof(DataGridUtils), new UIPropertyMetadata(null));
We need to set this property on every cell in our DataGrid. I didn't find a good solution to do this in XAML, so for now I set it in the converter before I retrieve the information. (suggestions for improvement appreciated)
Converter:
public class CellToEnabledConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var cell = values[0] as DataGridCell;
DataGridTextColumn column = cell.Column as DataGridTextColumn;
//you should probably check if column is null after casting.
Binding b = column.Binding as Binding;
//Any suggestions on how to create a Binding to the parent object properly?
//I needed this workaround since I bind `MyObject.Value` to the `DataGridTextColumn`,
//but need a reference to `MyObject` here.
Binding b1 = new Binding(b.Path.Path.Split('.')[0]){ Source = cell.DataContext };
cell.SetBinding(DataGridUtils.CellModelProperty, b1);
CellModel c = DataGridUtils.GetCellModel(cell);
return c.IsEnabled;
}
Now we can define a global Style in XAML and apply it to the whole DataGrid instead of a single column.
<Window.Resources>
<converter:CellToEnabledConverter x:Key="CellToEnabledConverter" />
<Style x:Key="DataGridCellStyle" TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Value="False">
<DataTrigger.Binding>
<!--This Converter works only on DataGridTextColumns with this minimal example!-->
<Binding Converter="{StaticResource CellToEnabledConverter}">
<Binding RelativeSource="{RelativeSource Self}" />
</Binding>
</DataTrigger.Binding>
<!--Setters-->
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<DataGrid CellStyle="{StaticResource DataGridCellStyle}">
<DataGridTextColumn Binding="{Binding MyObject.Value}"/>
</DataGrid>
Since i found several comments on the net stating that "styling a cell depending on its value just is not possible with the current DataGrid", i hope this workaround helps someone out.
I have been trying another solution for your problem.
<Style x:Key="DataGridCellStyle" TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=., RelativeSource={RelativeSource Self}, Converter={StaticResource DataGridCellToBooleanConverter}, ConverterParameter=IsEnabled}" Value="True">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
</Style.Triggers>
</Style>
<DataGrid CellStyle="{StaticResource DataGridCellStyle}">
<DataGrid.Columns>
<DataGridTextColumn Header="MyObject1" Binding="{Binding MyObject1}" />
<DataGridTextColumn Header="MyObject2" Binding="{Binding MyObject2}" />
</DataGrid.Columns>
</DataGrid>
In the other hand, I assume the ItemsSource of your DataGrid is a collection of Element objects (or something similar, of course)
public class Element
{
public string Name { get; set; }
public MyObject MyObject1 { get; set; }
public MyObject MyObject2 { get; set; }
}
public class MyObject
{
public string Name { get; set; }
public bool IsEnabled { get; set; }
public override string ToString()
{
return Name;
}
}
Finally, the converter:
public class DataGridCellToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string propertyToAppend = parameter as string;
var cell = value as DataGridCell;
var column = cell.Column as DataGridTextColumn;
Binding b = column.Binding as Binding;
Binding b1 = new Binding(string.Join(".", b.Path.Path, propertyToAppend)) { Source = cell.DataContext };
CheckBox dummy = new CheckBox();
dummy.SetBinding(CheckBox.IsCheckedProperty, b1);
return dummy.IsChecked;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
The tricky part is using the ConverterParameter in order to pass the name of the property you want to bind in the DataTrigger.
P.S. You can use reflection instead of the hacky CheckBox dummy element, but this works for me.
Hope this helps
The only thing I can think of is switching each DataGridTextColumn to a DataGridTemplateColumn and inside each CellTemplate add some ContentControl whose DataContext is bound to the property that goes in that column.
That way you can create a reusable Style for that ContentControl, since the DataGridCell hasn't been of any help for you :P
<Style x:Key="MyObjectStyle" TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<!-- your TextBlock and stuff -->
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled, PresentationTraceSources.TraceLevel=High, Converter={StaticResource debugger}}" Value="False">
<!-- some setters -->
</DataTrigger>
</Style.Triggers>
</Style>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentControl Content="{Binding MyObject}"
Style="{StaticResource MyObjectStyle}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
You have to fix the sintax of your DataTrigger first, something like this:
<DataGridTextColumn Binding="{Binding MyObject}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding MyObject.IsEnabled, PresentationTraceSources.TraceLevel=High, Converter={StaticResource debugger}}" Value="False">
<!-- some setters -->
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
Pay attention to the Binding property of the DataTrigger. Is in that property where you have to write your Path, in your case IsEnabled due to the fact that the DataContext in each DataGridCell will be an instance of MyObject object. You don't need to use the RelativeSource because your Binding is pointing to MyObject, as said before.
If you want to create this style as a resource you can do this:
<Style x:Key="cellStyle" TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=MyObject.IsEnabled, PresentationTraceSources.TraceLevel=High, Converter={StaticResource debugger}}" Value="False">
<!-- some setters -->
</DataTrigger>
</Style.Triggers>
</Style>

WPF: How can I disable one button if my window has any validation error?

I have some (>20) controls in a window, each is bound to a property of a ViewModel.
The ViewModel implements IDataErrorInfo, in order to do some validations, and it works well.
Now I add a button something like "Commit" to the window. I want to disable the button if any control has validation error.
Although I can use DataTrigger to do the trick like this:
<Button Content="Commit">
<Button.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=control1, Path=(Validation.HasError)}" Value="True">
<Setter Property="Button.IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=control2, Path=(Validation.HasError)}" Value="True">
<Setter Property="Button.IsEnabled" Value="False" />
</DataTrigger>
<!-- DataTriggers for control3, 4, 5... -->
</Style.Triggers>
</Style>
</Button.Style>
</Button>
That'll be a long XAML code because I have 20+ controls in this window, so I wonder is there a better solution?
Maybe you should create a command in ViewModel.
Something like this:
class ViewModel
{
public ICommand CommitCommand{ get; private set; }
public ViewModel()
{
CommitCommand = new RelayCommand(Commit, CanCommit);
}
private void Commit(object parameter)
{
// button click handler
}
private bool CanCommit(object parameter)
{
// check: view model has errors
}
}
Implement ICommand interface you can get here: Wpf Tutorial
Xaml code:
<Button Command={Binding CommitCommand}/>

WPF switch binding with trigger

I'm trying to switch the ItemsSource property on a ComboBox via triggers on a checkbox. Here is my code:
<CheckBox Content="Test" VerticalAlignment="Center" Margin="5,0,0,0">
<CheckBox.Triggers>
<Trigger Property="CheckBox.IsChecked" Value="True">
<Setter TargetName="MyComboBox" Property="ComboBox.ItemsSource" Value="{Binding A}" />
</Trigger>
<Trigger Property="CheckBox.IsChecked" Value="False">
<Setter TargetName="MyComboBox" Property="ComboBox.ItemsSource" Value="{Binding B}" />
</Trigger>
</CheckBox.Triggers>
</CheckBox>
As you can see, the intended purpose is to switch between binding "A" and binding "B" depending on the checkbox's IsChecked state. I've seen a lot of people put these triggers in a Style, but that gets rid of my window theme, which I want to keep. Additionally, I'd like this to be in XAML only as I need to apply this sort of binding switch to multiple combo box / checkbox pairs in my application.
The problem I'm having is that when I put in the above code my application crashes on startup! I've isolated it to the trigger code above (removing that removes the crash). Any help is appreciated!
I'm guessing that MyComboBox is not contained in the CheckBox and is therefore out of the naming scope that the Trigger is defined.
Instead of adding the trigger to the CheckBox, why not add it to the ComboBox and binding the CheckBox.IsChecked property to a property in your view model, like so:
<CheckBox IsChecked="{Binding ShowComboBoxItemsA}"/>
<ComboBox ItemsSource="{Binding A}">
<ComboBox.Triggers>
<DataTrigger Binding="{Binding ShowAComboBoxItems}" Value="False">
<Setter Property="ItemsSource" Value="{Binding B}"/>
</DataTrigger>
</ComboBox.Triggers>
</ComboBox>
The other option would be bind the CheckBox.IsChecked property to a property in your view model, as in the first, but then in your setter update the value of the ComboBoxItems.
<CheckBox IsChecked="{Binding ShowComboBoxItemsA}"/>
<ComboBox ItemsSource="{Binding ComboBoxItems}"/>
public List<object> ItemsA { get; set; }
public List<object> ItemsB { get; set; }
bool showComboBoxItemsA;
public bool ShowComboBoxItemsA
{
get { return showComboBoxItemsA; }
set
{
if (showComboBoxItemsA != value)
{
showComboBoxItemsA = value;
OnPropertyChanged("ShowComboBoxItemsA");
if (showComboBoxItemsA)
ComboBoxItems = ItemsA;
else
ComboBoxItems = ItemsB;
}
}
}
List<object> comboBoxItems;
public List<object> ComboBoxItems
{
get { return comboBoxItems; }
set
{
comboBoxItems = value;
OnPropertyChanged("ComboBoxItems");
}
}

Categories