C# passing dependency properties in an attribute - c#

I am creating a self composing UserControl in WPF.
I have an attribute I adorn the properties of my entity with that instructs my SelfComposingUserControl what to do.
If I want a property to be edited by a specific UI Control I pass this in my attribute.
In my attribute, I'm really not sure how to pass which property on the UI Control I would like bound to my entity property.
Can anybody help?
Here is a stripped down version of my UIEditableAttribute:
public class UIEditableAttribute : Attribute
{
/// <summary>
/// UIControl to edit the property
/// </summary>
public Type UIControl { get; set; }
/// <summary>
/// UIControl dependency property that binds to the property
/// </summary>
public DependencyProperty UIControlValueProperty { get; set; }
}
And here is an example of a property using the attribute
private int _numberOfRows;
[UIEditable(DisplayGroup = "B", UIControl = typeof(RadNumericUpDown), UIControlValueProperty = RadNumericUpDown.ValueProperty)]
public int NumberOfRows
{
get { return _numberOfRows; }
set { CheckPropertyChanged(ref _numberOfRows, value); }
}
In the SelfComposingUserControl, I have got around this by using a switch statement on the type of UIControl that binds the property to the correct dependency property. I would however like to specify at the property level.
Many thanks in advance.

The answer is to pass the UIControlValueProperty as a string i.e. "ValueProperty" in the attribute, then get this useful function;
Get Dependency Property By Name
to get the dependency property from the type or object.

Related

Catel framework - Lazy property

I'm trying to create a lazy property with Catel framework. Is there a way to do it?
When I'm creating a property in ViewModel like this:
#region Photos property
/// <summary>
/// Gets or sets the Photos value.
/// </summary>
public FastObservableCollection<Photo> Photos
{
get
{
var temp = GetValue<FastObservableCollection<Photo>>(PhotosProperty);
if (temp == null)
Photos = SelectedPatient.GetPhotos();
return GetValue<FastObservableCollection<Photo>>(PhotosProperty);
}
set { SetValue(PhotosProperty, value); }
}
/// <summary>
/// Photos property data.
/// </summary>
public static readonly PropertyData PhotosProperty = RegisterProperty("Photos", typeof (FastObservableCollection<Photo>));
#endregion
the get function is called even without binding, so my lazy property initializes while ViewModel is initializing.
Is there a way to do it?
There is only 1 way to implement "lazy properties", and that is by using the Lazy<> class. The reason for this is that for some mappings (such as view model to model, etc), Catel uses SetValue directly instead of the property wrapper (compare Catel properties with dependency properties).

How to write a custom dependecy property and data bind to custom type?

I have a project in winrt environment where I am trying to extend the functionality of the standard GridView control by extending it. The goal is to change the SelectedItems behaviour of the GridView.
public class myGridView : GridView
{
/// <summary>
/// My replacement of SelectedItems
/// </summary>
public IObservableVector<object> appItems
{
get { return GetValue(AppSelectedItemsProperty) as IObservableVector<object>; }
set { SetValue(AppSelectedItemsProperty, value);
appItems.VectorChanged += AppSelectedItemsChanged;
}
}
/// <summary>
/// Identifies the AppSelectedItems dependency property.
/// </summary>
public static readonly DependencyProperty AppSelectedItemsProperty =
DependencyProperty.Register(
"appItems",
typeof(IObservableVector<object>),
typeof(AppGridView),
new PropertyMetadata(null, AppItemsPropertyCallback));
….
….
...
}
In my XAML file I have the following..
<xx
…….
<appControls:AppGridView appItems="{Binding ContactsListSelectedItems, Mode=TwoWay } }">
.…
…
</appControls:AppGridView >
…..
…….
/xx>
The final piece of code is my MVVM class that is bound to the Datacontext.
public class myModel: baseModel
{
……
……..
/// <summary>
/// Not Working
/// </summary>
private IObservableVector<Contact> _ContactsListSelectedItems;
public IObservableVector<Contact> ContactsListSelectedItems
{
get
{
return (IObservableVector<Contact>)_ContactsListSelectedItems;
}
set
{
SetProperty<IObservableVector<Contact>>(ref _ContactsListSelectedItems, value);
}
}
….
….
}
I found a implementation of IObservableVector here : https://gist.github.com/runceel/2437074
The data binding to ContactsListSelectedItems are not working giving the following Error:
Error: Cannot get 'ContactsListSelectedItems' value (type 'Object') from type 'Consius.ActiveWork.Pages.ContactPage.ContactPageViewModel, Consius.ActiveWork, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. BindingExpression: Path='ContactsListSelectedItems' DataItem='Consius.ActiveWork.Pages.ContactPage.ContactPageViewModel, Consius.ActiveWork, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'; target element is 'Consius.ActiveWork.Controls.AppGridView' (Name='ContactsList'); target property is 'appItems' (type 'IObservableVector`1<Object>').
If I change the type of ContactsListSelectedItems to:
IObservableVector<object>
It all works well.
This is not a acceptable solution for me, writing my MVVM class with using the class object.
Is there anyone out there that can give me a hint whats wrong?
Have you tried with ObservableCollection instead of IObservableVector and that custom implementation you found?
I am researching this same problem at the moment. There seem to be two problems.
One, if you move your type (contact) to a WinRT Component project, it gets rid of the exception that the type cannot be instantiated because it is not a legal WinRT type, but then there is a second problem that when the type is not object, the enumerator is used instead of a virtualization and the indexer. So far I cannot see a way around the problem other than using object...

Extending an existing control for MVVM

I am tring to extend an existing microsoft control called the PivotViewer.
This control has an existing property that I want to expose to my ViewModel.
public ICollection<string> InScopeItemIds { get; }
I have created an inherited class called CustomPivotViewer and I want to create a Dependency Property that I can bind to that will expose the values held in InScopeItemIds in the base class.
I have spent a fair while reading up about DependencyPropertys and am becomming quite disheartened.
Is this even possible?
You only need a DependencyProperty is you want it to be bindable, meaning: if you want to have, for example, a MyBindableProperty property in your control, with which you want to be able to do:
MyBindableProperty={Binding SomeProperty}
if, however, you want other DependencyProperties to bind to it, any property (either a DependencyProperty or a normal one) can be used.
I'm not sure what you really need, maybe you can clarify more, but if it's the first scenario that you want to implement, you can do it as follows:
create a DependencyProperty, let's call it BindableInScopeItemIds, like so:
/// <summary>
/// BindableInScopeItemIds Dependency Property
/// </summary>
public static readonly DependencyProperty BindableInScopeItemIdsProperty =
DependencyProperty.Register("BindableInScopeItemIds", typeof(ICollection<string>), typeof(CustomPivotViewer),
new PropertyMetadata(null,
new PropertyChangedCallback(OnBindableInScopeItemIdsChanged)));
/// <summary>
/// Gets or sets the BindableInScopeItemIds property. This dependency property
/// indicates ....
/// </summary>
public ICollection<string> BindableInScopeItemIds
{
get { return (ICollection<string>)GetValue(BindableInScopeItemIdsProperty); }
set { SetValue(BindableInScopeItemIdsProperty, value); }
}
/// <summary>
/// Handles changes to the BindableInScopeItemIds property.
/// </summary>
private static void OnBindableInScopeItemIdsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = (CustomPivotViewer)d;
ICollection<string> oldBindableInScopeItemIds = (ICollection<string>)e.OldValue;
ICollection<string> newBindableInScopeItemIds = target.BindableInScopeItemIds;
target.OnBindableInScopeItemIdsChanged(oldBindableInScopeItemIds, newBindableInScopeItemIds);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the BindableInScopeItemIds property.
/// </summary>
protected virtual void OnBindableInScopeItemIdsChanged(ICollection<string> oldBindableInScopeItemIds, ICollection<string> newBindableInScopeItemIds)
{
}
in the OnBindableInScopeItemIdsChanged, you can update the inner collection (InScopeItemIds)
remember that the property you want to expose is read-only (it has no "setter"), so you might need to update it as so:
protected virtual void OnBindableInScopeItemIdsChanged(ICollection<string> oldBindableInScopeItemIds, ICollection<string> newBindableInScopeItemIds)
{
InScopeItemIds.Clear();
foreach (var itemId in newBindableInScopeItemIds)
{
InScopeItemIds.Add(itemId);
}
}
Hope this helps :)
EDIT:
I realized misunderstandings and here is a new version (in the context of the original question):
So, you can use the property you need for the binding, with following circumstances having in mind:
as this property is read-only, you will not be able to use it for 2-way binding.
as far as the containing type does not implement INotifyPropertyChanged, your target control used to display the data will not be notified about the changes to the property value.
as far as the returned by this property value does not implement INotifyCollectionChanged (one example is ObservableCollection<T>), the changes to the collection will not be affected on the target control which is used to display it.

How to document a class property

What is the correct syntax for an XML comment for a class property?
In response to a request for explicit examples, the following extract is from StyleCop help document, "SA1623: PropertySummaryDocumentationMustMatchAccessors":
The property’s summary text must begin with wording describing the types of accessors exposed within the property. If the property contains only a get accessor, the summary must begin with the word “Gets”. If the property contains only a set accessor, the summary must begin with the word “Sets”. If the property exposes both a get and set accessor, the summary text must begin with “Gets or sets”.
For example, consider the following property, which exposes both a get and set accessor. The summary text begins with the words “Gets or sets”.
/// <summary>
/// Gets or sets the name of the customer.
/// </summary>
public string Name
{
get { return this.name; }
set { this.name = value; }
}
If the property returns a Boolean value, an additional rule is applied. The summary text for Boolean properties must contain the words “Gets a value indicating whether”, “Sets a value indicating whether”, or “Gets or sets a value indicating whether”. For example, consider the following Boolean property, which only exposes a get accessor:
/// <summary>
/// Gets a value indicating whether the item is enabled.
/// </summary>
public bool Enabled
{
get { return this.enabled; }
}
In some situations, the set accessor for a property can have more restricted access than the get accessor. For example:
/// <summary>
/// Gets the name of the customer.
/// </summary>
public string Name
{
get { return this.name; }
private set { this.name = value; }
}
In this example, the set accessor has been given private access, meaning that it can only be accessed by local members of the class in which it is contained. The get accessor, however, inherits its access from the parent property, thus it can be accessed by any caller, since the property has public access.
In this case, the documentation summary text should avoid referring to the set accessor, since it is not visible to external callers.
StyleCop applies a series of rules to determine when the set accessor should be referenced in the property’s summary documentation. In general, these rules require the set accessor to be referenced whenever it is visible to the same set of callers as the get accessor, or whenever it is visible to external classes or inheriting classes.
The specific rules for determining whether to include the set accessor in the property’s summary documentation are:
1.The set accessor has the same access level as the get accessor. For example:
/// <summary>
/// Gets or sets the name of the customer.
/// </summary>
protected string Name
{
get { return this.name; }
set { this.name = value; }
}
2.The property is only internally accessible within the assembly, and the set accessor also has internal access. For example:
internal class Class1
{
/// <summary>
/// Gets or sets the name of the customer.
/// </summary>
protected string Name
{
get { return this.name; }
internal set { this.name = value; }
}
}
internal class Class1
{
public class Class2
{
/// <summary>
/// Gets or sets the name of the customer.
/// </summary>
public string Name
{
get { return this.name; }
internal set { this.name = value; }
}
}
}
3.The property is private or is contained beneath a private class, and the set accessor has any access modifier other than private. In the example below, the access modifier declared on the set accessor has no meaning, since the set accessor is contained within a private class and thus cannot be seen by other classes outside of Class1. This effectively gives the set accessor the same access level as the get accessor.
public class Class1
{
private class Class2
{
public class Class3
{
/// <summary>
/// Gets or sets the name of the customer.
/// </summary>
public string Name
{
get { return this.name; }
internal set { this.name = value; }
}
}
}
}
4.Whenever the set accessor has protected or protected internal access, it should be referenced in the documentation. A protected or protected internal set accessor can always been seen by a class inheriting from the class containing the property.
internal class Class1
{
public class Class2
{
/// <summary>
/// Gets or sets the name of the customer.
/// </summary>
internal string Name
{
get { return this.name; }
protected set { this.name = value; }
}
}
private class Class3 : Class2
{
public Class3(string name) { this.Name = name; }
}
}
Install this: http://submain.com/products/ghostdoc.aspx
Right-click on the property, select 'Document This'.
Fill in the blanks.
According to MSDN, link, it appears there isn't an official tag for Class Properties. But, I would use something like this:
/// <summary>Here is an example of a propertylist:
/// <list type="Properties">
/// <item>
/// <description>Property 1.</description>
/// </item>
/// <item>
/// <description>Property 2.</description>
/// </item>
/// </list>
/// </summary>
I'd suggest to use StyleCop. It does not only enforce (a bit to strong for my taste) you to comment, but also gives you a hint how the comments should be startet.
According to C# documentation the keyword <value> is used to desrcibe properties.
Implementation would look like this:
/// <value>Description goes here.</value>
public string MyProperty { get; set; }
source: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/documentation-comments#d319-value
Using <summary> should work too and even though I'm still learning C# it seems the documentation is more of a recommendation than a PEP8-like guide. So I think as long as one's code is consistent it comes down to personal preference and/or company guidelines.

Cannot bind to the property or column [...] on the DataSource

I am trying to bind Font property of System.Windows.Forms.Label to a property of my class (via forms designer).
This is the exception I am seeing "Cannot bind to the property or column HeaderText on the DataSource"
I tried making my class static and make it expose static properties - it didn't help.
The generated code looks like this:
this.WindowTitle.DataBindings.Add(new System.Windows.Forms.Binding("Font", this.fontManagerBindingSource, "HeaderText", true));
//
// fontManagerBindingSource
//
this.fontManagerBindingSource.DataSource = typeof(FontDefinitions.FontManager);
Here is the font manager class:
public class FontManager
{
/// <summary>
/// Gets or sets HeaderText.
/// </summary>
public static Font HeaderText
{
get { return new Font("Tahoma", 42); }
}
}
What am I doing wrong? Under what circumstances a property can not be bound?
Why do you want the property to be static? Its working if you make it non-static.

Categories

Resources