I want to execute a command in my viewmodel when the user presses enter in a TextBox.
The command works when bound to a button.
<Button Content="Add" Command="{Binding Path=AddCommand}" />
But I can't bring it to work from the TextBox.
I tried an Inputbinding, but it didn't work.
<TextBox.InputBindings>
<KeyBinding Command="{Binding Path=AddCommand}" Key="Enter"/>
</TextBox.InputBindings>
I also tried to set the working button as default, but it doesn't get executed when enter is pressed.
Thanks for your help.
I know I am late to the party, but I got this to work for me. Try using Key="Return" instead of Key="Enter"
Here is the full example
<TextBox Text="{Binding FieldThatIAmBindingToo, UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Command="{Binding AddCommand}" Key="Return" />
</TextBox.InputBindings>
</TextBox>
Make sure to use UpdateSourceTrigger=PropertyChanged in your binding, otherwise the property will not be updated until focus is lost, and pressing enter will not lose focus...
Hope this was helpful!
You have probably not made the command a property, but a field. It only works to bind to properties. Change your AddCommand to a property and it will work. (Your XAML works fine for me with a property instead of a field for the command -> no need for any code behind!)
Here's an attached dependency property I created for this. It has the advantage of ensuring that your text binding is updated back to the ViewModel before the command fires (useful for silverlight which doesn't support the property changed update source trigger).
public static class EnterKeyHelpers
{
public static ICommand GetEnterKeyCommand(DependencyObject target)
{
return (ICommand)target.GetValue(EnterKeyCommandProperty);
}
public static void SetEnterKeyCommand(DependencyObject target, ICommand value)
{
target.SetValue(EnterKeyCommandProperty, value);
}
public static readonly DependencyProperty EnterKeyCommandProperty =
DependencyProperty.RegisterAttached(
"EnterKeyCommand",
typeof(ICommand),
typeof(EnterKeyHelpers),
new PropertyMetadata(null, OnEnterKeyCommandChanged));
static void OnEnterKeyCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
ICommand command = (ICommand)e.NewValue;
FrameworkElement fe = (FrameworkElement)target;
Control control = (Control)target;
control.KeyDown += (s, args) =>
{
if (args.Key == Key.Enter)
{
// make sure the textbox binding updates its source first
BindingExpression b = control.GetBindingExpression(TextBox.TextProperty);
if (b != null)
{
b.UpdateSource();
}
command.Execute(null);
}
};
}
}
You use it like this:
<TextBox
Text="{Binding Answer, Mode=TwoWay}"
my:EnterKeyHelpers.EnterKeyCommand="{Binding SubmitAnswerCommand}"/>
You need to define Gesture instead of Key property of the KeyBinding:
<TextBox.InputBindings>
<KeyBinding Gesture="Enter" Command="{Binding AddCommand}"/>
</TextBox.InputBindings>
In addition to Mark Heath's answer, I took the class one step further by implementing Command Parameter attached property in this way;
public static class EnterKeyHelpers
{
public static ICommand GetEnterKeyCommand(DependencyObject target)
{
return (ICommand)target.GetValue(EnterKeyCommandProperty);
}
public static void SetEnterKeyCommand(DependencyObject target, ICommand value)
{
target.SetValue(EnterKeyCommandProperty, value);
}
public static readonly DependencyProperty EnterKeyCommandProperty =
DependencyProperty.RegisterAttached(
"EnterKeyCommand",
typeof(ICommand),
typeof(EnterKeyHelpers),
new PropertyMetadata(null, OnEnterKeyCommandChanged));
public static object GetEnterKeyCommandParam(DependencyObject target)
{
return (object)target.GetValue(EnterKeyCommandParamProperty);
}
public static void SetEnterKeyCommandParam(DependencyObject target, object value)
{
target.SetValue(EnterKeyCommandParamProperty, value);
}
public static readonly DependencyProperty EnterKeyCommandParamProperty =
DependencyProperty.RegisterAttached(
"EnterKeyCommandParam",
typeof(object),
typeof(EnterKeyHelpers),
new PropertyMetadata(null));
static void OnEnterKeyCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
ICommand command = (ICommand)e.NewValue;
Control control = (Control)target;
control.KeyDown += (s, args) =>
{
if (args.Key == Key.Enter)
{
// make sure the textbox binding updates its source first
BindingExpression b = control.GetBindingExpression(TextBox.TextProperty);
if (b != null)
{
b.UpdateSource();
}
object commandParameter = GetEnterKeyCommandParam(target);
command.Execute(commandParameter);
}
};
}
}
Usage:
<TextBox Text="{Binding Answer, Mode=TwoWay}"
my:EnterKeyHelpers.EnterKeyCommand="{Binding SubmitAnswerCommand}"
my:EnterKeyHelpers.EnterKeyCommandParam="your parameter"/>
Related
In WPF I can easily create command and command handler in ViewModel and easily connect it to Button control in XAML (View) by following standard MVVM design pattern . I can also define InputBindings and CommandBindings in XAML (View) to handle key down and then execute command in ViewModel.
Currently have one command on button and it is executed when button is clicked.
But how can I, at the same time, handle click on the button and if key modifier is pressed, and then execute another command? Key modifier would be Left or Right Alt.
Do this in XAML by setting the modifiers property on the input binding example below.
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding SaveCommand}" Modifiers="Alt"/>
<KeyBinding Key="Enter" Command="{Binding AnotherSaveCommand}"/>
</TextBox.InputBindings>
You could implement an attached behaviour:
namespace WpfApplication1
{
public class CombinedMouseAndKeyCommandBehavior
{
public static readonly DependencyProperty KeyProperty = DependencyProperty.RegisterAttached("Key", typeof(Key),
typeof(CombinedMouseAndKeyCommandBehavior), new PropertyMetadata(Key.None, new PropertyChangedCallback(OnKeySet)));
public static Key GetKey(FrameworkElement element) => (Key)element.GetValue(KeyProperty);
public static void SetKey(FrameworkElement element, Key value) => element.SetValue(KeyProperty, value);
public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand),
typeof(CombinedMouseAndKeyCommandBehavior), new PropertyMetadata(null));
public static ICommand GetCommand(FrameworkElement element) => (ICommand)element.GetValue(CommandProperty);
public static void SetCommand(FrameworkElement element, ICommand value) => element.SetValue(CommandProperty, value);
private static void OnKeySet(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement fe = d as FrameworkElement;
fe.PreviewMouseLeftButtonDown += Fe_PreviewMouseLeftButtonDown;
}
private static void Fe_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
FrameworkElement fe = sender as FrameworkElement;
Key key = GetKey(fe);
ICommand command = GetCommand(fe);
if(key != Key.None && command != null && Keyboard.IsKeyDown(key))
{
command.Execute(null);
}
}
}
}
Usage:
<Button Content="Test command"
xmlns:local="clr-namespace:WpfApplication1"
local:CombinedMouseAndKeyCommandBehavior.Command="{Binding RemoveCommand}"
local:CombinedMouseAndKeyCommandBehavior.Key="F">
<Button.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding AddCommand }" />
</Button.InputBindings>
</Button>
Introduction to Attached Behaviors in WPF: https://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF
You may read pressed key only from focused WPF element. In your case you are able to get it from window(page).
XAML
<Window x:Class="Application.MainWindow"
mc:Ignorable="d"
Title="MainWindow"
KeyDown="MainWindow_OnKeyDown"
x:Name="RootKey">
Code-behind
private void MainWindow_OnKeyDown(object sender, KeyEventArgs e)
{
var dataContext = (MainPageViewModel) this.DataContext;
dataContext.KeyModifer = e.SystemKey.ToString();
}
ViewModel
internal class MainPageViewModel : ViewModelBase
{
public string KeyModifer { private get; set;}
...
}
I'm working on a Windows Phone app using Silverlight C# and XAML. My page contains a ListBox which renders a list of databound objects that the user can manipulate, i.e. add/rename/delete.
I've got it working that the add/rename of items is done in-place, i.e. by swapping a TextBlock for a TextBox depending on the state of the object (bool IsEditable property) and making use of a parameterized VisibilityConverter to manage the opposite Visibility states.
<UserControl.Resources>
<local:VisibilityConverter x:Key="VisibilityConverter" True="Visible" False="Collapsed"/>
<local:VisibilityConverter x:Key="InvertedVisibility" True="Collapsed" False="Visible"/>
</UserControl.Resources>
...
<TextBlock Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource InvertedVisibility}}" />
<TextBox Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource VisibilityConverter}}"/>
The thing is that I also want the TextBox to automatically grab focus when it becomes visible, so that the on-screen keyboard pops up without the user having to tap the TextBox.
Since there's no VisibilityChanged event on a regular TextBox, I subclassed TextBox to TextBox2 and added my own:
public class TextBox2 : TextBox
{
public TextBox2()
{
DefaultStyleKey = typeof(TextBox);
}
public static readonly DependencyProperty VisibilityChangedProperty = DependencyProperty.Register(
"VisibilityChanged",
typeof(string),
typeof(TextBox2),
new PropertyMetadata("Set the VisibilityChanged event handler"));
public event VisibilityChangedEventHandler VisibilityChanged;
public delegate void VisibilityChangedEventHandler(object sender, EventArgs e);
public new Visibility Visibility
{
get
{
return base.Visibility;
}
set
{
if (base.Visibility != value)
{
base.Visibility = value;
VisibilityChanged(this, new EventArgs());
}
}
}
}
Now my XAML looks like this:
<TextBlock Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource InvertedVisibility}}"/>
<local:TextBox2 Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource VisibilityConverter}}" VisibilityChanged="ListEdit_VisibilityChanged"/>
And the event handler like this:
void ListEdit_VisibilityChanged(object sender, EventArgs e)
{
TextBox textBox = (TextBox)sender;
if (textBox.Visibility == System.Windows.Visibility.Collapsed)
return;
textBox.Focus();
}
The TextBox2 renders properly and behaves just like a TextBox at runtime, but my VisibilityChanged event handler is not firing when the databinding flips the value of IsEditable.
IsEditable defines the Visibility and the TextBox2 does become visible correctly, so the databinding is working.
I can cause the event to fire programmatically by getting hold of the TextBox2 instance and setting the Visibility of that in code. That also works.
But this databinding scenario being responsible for setting the Visibility seems not to work.
Any ideas why not?
Here are 2 solutions that I use.
Solution 1 needs no sub class, but solution 2 is more reusable.
1. You can subscribe to the Loaded event of the TextBox, and force a focus, like so:
void TextBox_Loaded_Focus(object sender, System.Windows.RoutedEventArgs e) {
ForceFocusControl((Control)sender);
}
void ForceFocusControl(Control control) {
control.Focus();
if (FocusManager.GetFocusedElement() != control) {
Dispatcher.BeginInvoke(() => ForceFocusControl(control));
}
}
This solution goes into a recursive loop though, you might want to add some checks to make it safer.
2. Keep your subclass TextBox2, and rather create a private MyVisibility dependency property that you bind to the Visibility property of the base class, but also specify a DependencyProperty_Changed handler, like so:
/// <summary>
/// <see cref="TextBox2"/> will focus itself when it becomes visible.
/// </summary>
public sealed class TextBox2 : TextBox {
public TextBox2() {
SetBinding(TextBox2.MyVisibilityProperty, new Binding("Visibility") { Source = this });
}
static readonly DependencyProperty MyVisibilityProperty = DependencyProperty.Register(
/* name = */ "MyVisibilityProperty",
/* property type = */ typeof(Visibility),
/* owner type = */ typeof(TextBox2),
/* meta = */ new PropertyMetadata(MyVisibilityProperty_Changed));
static void MyVisibilityProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) {
TextBox2 TextBox2 = (TextBox2)d;
if (TextBox2.Visibility == Visibility.Visible) {
TextBox2.Focus();
}
}
}
This is how my TextBox2 class looks now:
public class TextBox2 : TextBox
{
public event VisibilityChangedEventHandler VisibilityChanged;
public delegate void VisibilityChangedEventHandler(object sender, EventArgs e);
public static readonly DependencyProperty VisibilityChangedProperty = DependencyProperty.Register(
"VisibilityChanged", typeof(VisibilityChangedEventHandler), typeof(TextBox2), null);
static readonly DependencyProperty MirrorVisibilityProperty = DependencyProperty.Register(
"MirrorVisibility", typeof(Visibility), typeof(TextBox2), new PropertyMetadata(MirrorVisibilityChanged));
public TextBox2()
{
SetBinding(TextBox2.MirrorVisibilityProperty, new Binding("Visibility") { Source = this });
}
static void MirrorVisibilityChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
((TextBox2)obj).VisibilityChanged(obj, null); // raise event
}
}
I'm implementing something like an autosuggestion control: I have a user control that contains a TextBox and a ListBox. When the user enters text I'm handing it with System.Windows.Interactivity behaviors and filling the ListBox with some values...
Everything works fine... but I want to enable the user to select items in the ListBox (i.e. to set Focus on the ListBox) when the down arrow key is pressed.
I know that it is possible to handle the KeyPressDown event of the TextBox in the code-behind .cs file but how can I avoid this?
If you already use Interactivity that should not be much of an issue, just implement your own TriggerAction that has the properties Key & TargetName to indentify when and what to focus. Set it in an EventTrigger for PreviewKeyDown.
Sample implementation & use:
<TextBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewKeyDown">
<t:KeyDownFocusAction Key="Down"
Target="{Binding ElementName=lbx}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
<ListBox Name="lbx" ItemsSource="{Binding Data}" />
class KeyDownFocusAction : TriggerAction<UIElement>
{
public static readonly DependencyProperty KeyProperty =
DependencyProperty.Register("Key", typeof(Key), typeof(KeyDownFocusAction));
public Key Key
{
get { return (Key)GetValue(KeyProperty); }
set { SetValue(KeyProperty, value); }
}
public static readonly DependencyProperty TargetProperty =
DependencyProperty.Register("Target", typeof(UIElement), typeof(KeyDownFocusAction), new UIPropertyMetadata(null));
public UIElement Target
{
get { return (UIElement)GetValue(TargetProperty); }
set { SetValue(TargetProperty, value); }
}
protected override void Invoke(object parameter)
{
if (Keyboard.IsKeyDown(Key))
{
Target.Focus();
}
}
}
Tested it and it works, note that KeyDown does not because the arrow keys are intercepted and marked as handled by the TextBox.
I don't think you can avoid it
What's wrong with capturing the KeyDown event of the TextBox and if it's an Up or Down arrow key, just trigger the ListBox.KeyDown event in the code behind?
I see no reason not to use code-behind in MVVM if it is to provide view-specific functionality such as focus
This answer is based on the one from H.B., and adds support for checking to see if the Ctrl key is pressed. This means it can handle keycombinations such as Ctrl-F for find.
XAML
<TextBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewKeyDown">
<t:KeyDownFocusAction Key="Down" Ctrl="True"
Target="{Binding ElementName=lbx}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
<ListBox Name="lbx" ItemsSource="{Binding Data}" />
Namespaces
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
See help on adding System.Windows.Interactivity.
DependencyProperty
public class KeyDownFocusAction : TriggerAction<UIElement>
{
public static readonly DependencyProperty KeyProperty =
DependencyProperty.Register("Key", typeof(Key), typeof(KeyDownFocusAction));
public Key Key
{
get { return (Key)GetValue(KeyProperty); }
set { SetValue(KeyProperty, value); }
}
public static readonly DependencyProperty CtrlProperty =
DependencyProperty.Register("Ctrl", typeof(bool), typeof(KeyDownFocusAction));
public bool Ctrl
{
get { return (bool)GetValue(CtrlProperty); }
set { SetValue(CtrlProperty, value); }
}
public static readonly DependencyProperty TargetProperty =
DependencyProperty.Register("Target", typeof(UIElement), typeof(KeyDownFocusAction), new UIPropertyMetadata(null));
public UIElement Target
{
get { return (UIElement)GetValue(TargetProperty); }
set { SetValue(TargetProperty, value); }
}
protected override void Invoke(object parameter)
{
if (Keyboard.IsKeyDown(Key))
{
if (Ctrl == true)
{
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
{
Target.Focus();
}
}
}
}
}
I'm using MVVM.
<ItemsControl ItemsSource="{Binding AllIcons}" Tag="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label HorizontalAlignment="Right">x</Label>
<Image Source="{Binding Source}" Height="100" Width="100" />
<Label HorizontalAlignment="Center" Content="{Binding Title}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
That looks fine. If I put a button in the stack panel using this command:
<Button Command="{Binding Path=DataContext.InvasionCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}" CommandParameter="{Binding}"/>
I'm able to capture the command. However, I want to execute the command binding when the mouse enters the stack panel, not when I click a button.
Any idea?
My wrong, input bindings does not solve the problem. You may use attached properties for this:
public static class MouseEnterCommandBinding
{
public static readonly DependencyProperty MouseEnterCommandProperty = DependencyProperty.RegisterAttached(
"MouseEnterCommand",
typeof(ICommand),
typeof(MouseEnterCommandBinding),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender)
);
public static void SetMouseEnterCommand(UIElement element, ICommand value)
{
element.SetValue(MouseEnterCommandProperty, value);
element.MouseEnter += (s,e) =>
{
var uiElement = s as UIElement;
var command = GetMouseEnterCommand(uiElement);
if (command != null && command.CanExecute(uiElement.CommandParameter))
command.Execute(uiElement.CommandParameter);
}
}
public static ICommand GetMouseEnterCommand(UIElement element)
{
return element.GetValue(MouseEnterCommandProperty) as ICommand;
}
}
First you need to declare a behavior for mouse enter. This basically translates the event into a command in your ViewModel.
public static class MouseEnterBehavior
{
public static readonly DependencyProperty MouseEnterProperty =
DependencyProperty.RegisterAttached("MouseEnter",
typeof(ICommand),
typeof(MouseEnterBehavior),
new PropertyMetadata(null, MouseEnterChanged));
public static ICommand GetMouseEnter(DependencyObject obj)
{
return (ICommand)obj.GetValue(MouseEnterProperty);
}
public static void SetMouseEnter(DependencyObject obj, ICommand value)
{
obj.SetValue(MouseEnterProperty, value);
}
private static void MouseEnterChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
UIElement uiElement = obj as UIElement;
if (uiElement != null)
uiElement.MouseEnter += new MouseEventHandler(uiElement_MouseEnter);
}
static void uiElement_MouseEnter(object sender, MouseEventArgs e)
{
UIElement uiElement = sender as UIElement;
if (uiElement != null)
{
ICommand command = GetMouseEnter(uiElement);
command.Execute(uiElement);
}
}
}
Then you just need to create that command in your view model and reference it in the view. The behaviors: namespace should just point to wherever you created that behavior. I use this pattern every time I need to translate an event into a command in a view model.
<Grid>
<StackPanel behaviors:MouseEnterBehavior.MouseEnter="{Binding MouseEnteredCommand}"
Height="150"
Width="150"
Background="Red">
</StackPanel>
</Grid>
You probably need to use InputBindings: http://msdn.microsoft.com/en-us/library/system.windows.input.inputbinding.aspx
I am using the Julmar helper classes for WPF so that I can call a custom ICommand on an event such as MouseEnter on a text box like so:
<TextBox Text="hmm">
<julmar:EventCommander.Mappings>
<julmar:CommandEvent Command="{Binding DataContext.IncreaseQueueTimeCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}" Event="MouseEnter" />
</julmar:EventCommander.Mappings>
</TextBox>
This works and calls the command, the problem is I need to pass an object as a parameter, does anyone know if this is possible? the documentation seems quite light.
Previously I was able to pass the object as a parameter like this:
<Button Content="Save" x:Name="SaveQueueTimeButton" Command="{Binding DataContext.SaveQueueTimeCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}" CommandParameter="{Binding}" />
But obviously this isn't what I need as it doesn't fire on a MouseEvent
Any help would be useful,
Thanks
You can solve this with the Behavior-Pattern. Basically you make a custom class with two dependency properties: Command and CommandParameter. You also register a handler for both properties.
In one of the handlers, you get your TextBox passed as a parameter. Now you can hook up to the events you are interested in. If now one of the registered event handlers is called, you can invoke the bound command with the bound command parameter.
Here is a code sample:
public class CommandHelper
{
//
// Attached Properties
//
public static ICommand GetCommand(DependencyObject obj)
{
return (ICommand)obj.GetValue(CommandProperty);
}
public static void SetCommand(DependencyObject obj, ICommand value)
{
obj.SetValue(CommandProperty, value);
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(CommandHelper), new UIPropertyMetadata(null));
public static object GetCommandParameter(DependencyObject obj)
{
return (object)obj.GetValue(CommandParameterProperty);
}
public static void SetCommandParameter(DependencyObject obj, object value)
{
obj.SetValue(CommandParameterProperty, value);
}
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.RegisterAttached("CommandParameter", typeof(object), typeof(CommandHelper), new UIPropertyMetadata(null));
//
// This property is basically only there to attach handlers to the control that will be the command source
//
public static bool GetIsCommandSource(DependencyObject obj)
{
return (bool)obj.GetValue(IsCommandSourceProperty);
}
public static void SetIsCommandSource(DependencyObject obj, bool value)
{
obj.SetValue(IsCommandSourceProperty, value);
}
public static readonly DependencyProperty IsCommandSourceProperty =
DependencyProperty.RegisterAttached("IsCommandSource", typeof(bool), typeof(CommandHelper), new UIPropertyMetadata(false, OnRegisterHandler));
//
// Here you can register handlers for the events, where you want to invoke your command
//
private static void OnRegisterHandler(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
FrameworkElement source = obj as FrameworkElement;
source.MouseEnter += OnMouseEnter;
}
private static void OnMouseEnter(object sender, MouseEventArgs e)
{
DependencyObject source = sender as DependencyObject;
ICommand command = GetCommand(source);
object commandParameter = GetCommandParameter(source);
// Invoke the command
if (command.CanExecute(commandParameter))
command.Execute(commandParameter);
}
}
And Xaml:
<TextBox Text="My Command Source"
local:CommandHelper.IsCommandSource="true"
local:CommandHelper.Command="{Binding MyCommand}"
local:CommandHelper.CommandParameter="MyParameter" />
If the Julmar CommandEvent doesn't have a CommandParameter property, I suggest you use Marlon Grech's Attached Command Behaviours instead. It's very similar but it provides a CommandParameter property.