I've created my own custom control in Xamarin in which I want to set a property from the xaml code.
<MyClass MyProperty="10" />
I've tried to use a BindableProperty in order to get it work, my code behind looks like:
public static readonly BindableProperty BindProp = BindableProperty.Create(
nameof(MyProperty),
typeof(int),
typeof(MyClass),
0);
public int MyProperty
{
get
{
return (int)GetValue(BindProp);
}
set
{
SetValue(BindProp, value);
}
}
I expedted that MyProperty should be initiated to 10. What am I doing wrong?
Related
I created an Interaction.Behavior behavior that needs to receive a variable amount of input.
For this, the behavior has a List<> Dependency property to receive content:
private static readonly DependencyPropertyKey FocusTargetsPropertyKey = DependencyProperty.RegisterReadOnly("Targets", typeof(List<FocusTarget>), typeof(StatefulFocusManagerBehavior), new PropertyMetadata(new List<FocusTarget>()));
public static readonly DependencyProperty FocusTargetsProperty = FocusTargetsPropertyKey.DependencyProperty;
public List<FocusTarget> Targets
{
get => (List<FocusTarget>)this.GetValue(FocusTargetsProperty);
set => this.SetValue(FocusTargetsProperty, value);
}
And the content is implemented as a class FocusTarget that derives from FrameworkElement:
public class FocusTarget : FrameworkElement
{
#region DepProp: FocusTarget
public static readonly DependencyProperty FocusTargetProperty = DependencyProperty.Register("Target", typeof(FrameworkElement), typeof(FocusTarget), new PropertyMetadata(null));
public FrameworkElement Target
{
get => (FrameworkElement)this.GetValue(FocusTargetProperty);
set => this.SetValue(FocusTargetProperty, value);
}
#endregion
#region DepProp: StateName
public static readonly DependencyProperty StateNameProperty = DependencyProperty.Register("StateName", typeof(string), typeof(FocusTarget), new PropertyMetadata(null));
public string StateName
{
get => (string)this.GetValue(StateNameProperty);
set => this.SetValue(StateNameProperty, value);
}
#endregion
}
The Behavior is declared as follows:
<b:Interaction.Behaviors>
<behav:StatefulFocusManagerBehavior FocusTarget="{Binding ElementName=txtResponse}">
<behav:StatefulFocusManagerBehavior.Targets>
<behav:FocusTarget Target="{Binding ElementName=txtResponse}" StateName="Text" />
<behav:FocusTarget Target="{Binding ElementName=QnAToggle}" StateName="Toggle"/>
</behav:StatefulFocusManagerBehavior.Targets>
</behav:StatefulFocusManagerBehavior>
</b:Interaction.Behaviors>
Now there is what works:
The behav:StatefulFocusManagerBehavior has its FocusTarget property binding is working as expected
The behav:FocusTarget instances hast their property StateName set as expected
The behav:FocusTarget instances have their Target property always set to null
I did suspect this could be a DataContext issue but could not verify nor dismiss it, leaving me puzzled on the possible issue and solution.
I tried to set the DataContext but this binding to is not working and giving me null:
<behav:FocusTarget Target="{Binding ElementName=txtResponse}"
StateName="Text"
DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}" />
Inheriting the data context and accessing elements from a behavior collection does not work that way, because the collection is not in the visual tree and not a FrameworkElement or Freezable that enable binding.
Change the FocusTargetsProperty to a FreezableCollection<FocusTarget> instead of a List<FocusTarget>. Furthermore, make sure that you assign a new instance of the collection in the constructor.
public class StatefulFocusManagerBehavior : Behavior<FrameworkElement>
{
private static readonly DependencyPropertyKey FocusTargetsPropertyKey = DependencyProperty.RegisterReadOnly("Targets", typeof(FreezableCollection<FocusTarget>), typeof(StatefulFocusManagerBehavior), new PropertyMetadata(null));
public static readonly DependencyProperty FocusTargetsProperty = FocusTargetsPropertyKey.DependencyProperty;
public FreezableCollection<FocusTarget> Targets
{
get => (FreezableCollection<FocusTarget>)this.GetValue(FocusTargetsProperty);
set => this.SetValue(FocusTargetsProperty, value);
}
public StatefulFocusManagerBehavior()
{
SetValue(FocusTargetsPropertyKey, new FreezableCollection<FocusTarget>());
}
}
Then, instead of inheriting from FrameworkElement in FocusTarget, derive from Freezable.
public class FocusTarget : Freezable
{
protected override Freezable CreateInstanceCore()
{
return new FocusTarget();
}
// ...your other code.
}
I am trying to set/bind a list property in a content view class in xaml.
This is my Class :
public class Myclass:ContentView
{
public static readonly BindableProperty TabItemSourceProperty = BindableProperty.Create(
"TabIndicatorItemSource",
typeof(IEnumerable<string>),
typeof(Myclass)
);
public IEnumerable<string> TabIndicatorItemSource {
get
{
return (IEnumerable<string>)GetValue(TabItemSourceProperty);
}
set
{
SetValue(TabItemSourceProperty, value);
}
}}
and This is my Xaml in ExampleClass.xaml.cs
local:Myclass x:Name="myCarouselView" TabTextSizeTabIndicatorItemSource ="{Binding tabListSource}"
And tabListSource is a List property in ExampleClass.cs.
However I get this type mismatch error. Where am I going wrong?
Bindable Properties need to adhere to a set naming convention. e.g. TabItemSourceProperty relates to TabItemSource
public class Myclass: ContentView
{
public static readonly BindableProperty TabItemSourceProperty = BindableProperty.Create(
"TabItemSource",
typeof(IEnumerable<string>),
typeof(Myclass)
);
public IEnumerable<string> TabItemSource {
get
{
return (IEnumerable<string>)GetValue(TabItemSourceProperty);
}
set
{
SetValue(TabItemSourceProperty, value);
}
}}
with
local:Myclass x:Name="myCarouselView" TabItemSource="{Binding tabListSource}"
I currently have a Dependency Property as such:
public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register("MyPropertyDefaults", typeof(ICollection<string>), typeof(MyPanel), new PropertyMetadata(new List<string>()));
public ICollection<string> MyProperty
{
get
{
return GetValue(MyPropertyProperty) as ICollection<string>;
}
set
{
this.SetValue(MyPropertyProperty, value);
}
}
The aim is that this subpanel will be passed a list via a binding, that the subpanel manipulates, and then the parent can read later. E.g.
<xaml:MyPanel MyProperty="{Binding MyPropertyList}" />
However, FxCop reports CollectionPropertiesShouldBeReadOnly and I need to remove the setter, which is required by the property. How do I fix this? What is the correct way to do what I am doing?
Declare the setter as private like this:
public class MyPanel : Panel
{
public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register("MyPropertyDefaults", typeof(ICollection<string>), typeof(MyPanel), new PropertyMetadata(new List<string>()));
public ICollection<string> MyProperty
{
get
{
return GetValue(MyPropertyProperty) as ICollection<string>;
}
private set
{
this.SetValue(MyPropertyProperty, value);
}
}
}
I have a UserControl that add a DependencyProperty for it .
public const string TextValuePropertyName = "TextValue";
public string TextValue
{
get
{
return (string)GetValue(TextValueProperty);
}
set
{
SetValue(TextValueProperty, value);
}
}
public static readonly DependencyProperty TextValueProperty = DependencyProperty.Register(
TextValuePropertyName,
typeof(string),
typeof(FormatUserControl),
new UIPropertyMetadata());
and use it in another Usercontrol
<local:FormatUserControl TextValue="{Binding Subject,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
When i use this don't set value for this property when i change Subject value?
Your FormatUserControl is the class and you should register the property for it not for the NumberFormatUserControl like this (I am not aware what is the relationship between the two user controls):
public static readonly DependencyProperty TextValueProperty = DependencyProperty.Register(
TextValuePropertyName,
typeof(string),
typeof(FormatUserControl),
new UIPropertyMetadata());
I have a usercontrol in which i want to expose a property called ExpressionText and in the
xaml a binding can be defined to this property.
So i created a dependency property
public static readonly DependencyProperty EditorText =DependencyProperty.Register("EditorText", typeof(string), typeof(MyUerControl));
and
public string ExpressionText
{
get
{
return (string)GetValue(EditorText);
}
set
{
SetValue(EditorText, value);
}
}
in the xaml i do this.
<controls:MyUerControl x:Name="textEditor" ExpressionText="{Binding
Path=Expression,Mode=TwoWay}" />
but i get
A binding cannot be set on ExpressionText property of type MyUserControl. Binding can be set
only on a depenedecy property of type Dependency object error.
Is there something wrong in my approach ? How do i solve this problem ?
This should work:
public static DependencyProperty EditorTextProperty = DependencyProperty.Register("ExpressionText", typeof(string), typeof(MyUserControl),
new PropertyMetadata(new PropertyChangedCallback((s, e) =>
{ })));
public string ExpressionText
{
get
{
return (string)base.GetValue(EditorTextProperty);
}
set
{
base.SetValue(EditorTextProperty, value);
}
}
You are defining EditorText as the name of your DependencyProperty. That is the name that is available publicly for you to bind to. If you want it to be called ExpressionText, then you need to register that as the name.
public static readonly DependencyProperty EditorText =
DependencyProperty.Register("ExpressionText", typeof(string), typeof(MyUerControl));