CollectionPropertiesShouldBeReadOnly and Dependency Properties - c#

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);
}
}
}

Related

How to write a behavior that can host a variable number of child properties/elements/xaml-tags

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.
}

Xaml Parse Exception - type mismatch between "Xamarin.Forms.Binding" and "System.Collections.Generic.IEnumerable`1[System.String]"

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}"

TypeInitialization Exception occurs while setting value to dependency property

I am developing a usercontrol in which i am registering dependency property as follows
public string TextBoxHint
{
get { return (string)GetValue(TextBoxHintProperty); }
set { SetValue(TextBoxHintProperty, value); }
}
public static readonly DependencyProperty TextBoxHintProperty =
DependencyProperty.Register("TextBoxHint",
typeof(string),
typeof(AutoCompleteBox),
new PropertyMetadata("Search"));
and i am using the usercontrol as follows in another page
<localControls:AutoCompleteBox TextBoxHint="Search Task" />
Execution of above code is causing a TypeInitialization Exception at SetValue() function.
Can anybody point out what is wrong with the code ???
Thanks In advance...
Dependency Properties need a SetValue and GetValue function for that property so it should be something like this.
public string ToolTipText
{
get { return (string)this.GetValue(ToolTipTextProperty); }
set { this.SetValue(ToolTipTextProperty, value); }
}
public static object GetToolTipText(DependencyObject target)
{
return (object)target.GetValue(ToolTipTextProperty);
}
public static void SetToolTipText(DependencyObject target, Object value)
{
target.SetValue(ToolTipTextProperty, value);
}
public static readonly DependencyProperty ToolTipTextProperty = DependencyProperty.RegisterAttached("ToolTipText", typeof(string), typeof(Controls.ProgressSlider), new PropertyMetadata("0%"));

Binding to a property in a UserControl

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));

WPF C# Custom UserControl How To add a Property which accepts an Binding

I'm trying to design a CustomUserControl which consits of an TextEditor and a PopUp...
So the Popup control should be binded to a list...
I called it BindingList. This Property should accept any types like ObservableCollection, List, Ienumerable for example(Collections)...
<my:CustomControl BindingList="{Binding Path=Collection}"
public IEnumerable<object> BindingList
{
get { return (IEnumerable<object>)GetValue(BindingListProp); }
set { SetValue(BindingListProp, value); }
}
The BindinglistProp
public static readonly DependencyProperty BindingListProp = DependencyProperty.Register(??????
I have no clue how it should look like that it can accept a binding.
And how should i deal with the Collection which is passed? when it is of a type which i don`t know
like
class Person
{
private string _Name;
private string _forename;
public string Name
{
get { return _Name; }
set
{
_Name = value;
}
}
public string Forename
{
get { return _forename; }
set
{
_forename = value;
}
}
}
Thanks for any hints, tutorials or code snippets.
sincerely
Mark
public IObservable<object> BindingList
{
get { return (IObservable<object>)base.GetValue(BindingListProperty); }
set { base.SetValue(BindingListProperty, value); }
}
public static DependencyProperty BindingListProperty =
DependencyProperty.Register(
"BindingList",
typeof(IObservable<object>),
typeof(CustomControl),
new PropertyMetadata(null));
Look to the CollectionViewSource.GetDefaultView to work with any collection in common way.

Categories

Resources