Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collection-Type Dependency Properties #1878

Closed
robloo opened this issue Aug 21, 2019 — with docs.microsoft.com · 8 comments
Closed

Collection-Type Dependency Properties #1878

robloo opened this issue Aug 21, 2019 — with docs.microsoft.com · 8 comments
Assignees
Labels
doc-enhancement feedback is about suggested additions/improvements to the article, but customer is not blocked eng-triaged platform/tech Pri2 product-question general "how do I do X" questions uwp/prod winui/tech

Comments

Copy link

robloo commented Aug 21, 2019

What is the 'correct' way to support collection dependency properties in UWP? In WPF this was a defined case:

https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/collection-type-dependency-properties


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

Copy link
Author

robloo commented Aug 22, 2019

Fiddling around it seems the 'correct' way in UWP is to do something like this:

        /// <summary>
        /// Identifies the <see cref="SelectedItems"/> dependency property.
        /// </summary>
        public static readonly DependencyProperty SelectedItemsProperty =
            DependencyProperty.Register(nameof(SelectionBox2.SelectedItems),
                                        typeof(IList<SelectionItem>),
                                        typeof(SelectionBox2),
                                        PropertyMetadata.Create(new CreateDefaultValueCallback(() =>
                                            {
                                                return new List<SelectionItem>();
                                            })));

That avoids sharing the same List reference with all instances. However, it is only safe through the property accessor (which you can make get only). Through binding, it would be possible to set a new list entirely it seems which is why WPF had read-only dependency properties. If you are dealing with an ObservableCollection there are even more complexities this causes because you have to detect the new collection and then hookup event handlers. So, I'm still not sure the 'best' way to do this in UWP. Some clear documentation from Microsoft would be a big help.

Also see: https://stackoverflow.com/questions/45335237/how-to-define-a-dependencyproperty-for-a-collection-type-in-uwp/45345057#45345057

@jwmsft jwmsft added winui/tech doc-enhancement feedback is about suggested additions/improvements to the article, but customer is not blocked product-question general "how do I do X" questions labels Aug 22, 2019
@jevansaks
Copy link
Contributor

Almost all of our collection properties are get-only for this type of reason. We are looking into opening this up in the future. Generally we have the "default value" be null and then the getter returns a collection.

@robloo
Copy link
Author

robloo commented Aug 24, 2019

Yes, I understand collection properties should be get-only and that follows C# and .net conventions. Therefore, for back-end classes I would normally just write an IList field in the class and expose it as a get-only property. Something like what is below.

ObservableCollection<SelectionItem> list = new ObservableCollection<SelectionItem>();

public IList<SelectionItem> SelectedItems
{
    get { return list; }
}

However, I understand to fully support the binding system/convention (at least in WPF) the field should instead be a dependency property. Therefore, right now what I have in UWP is:

public static readonly DependencyProperty SelectedItemsProperty =
            DependencyProperty.Register(nameof(SelectionBox2.SelectedItems),
                   typeof(IList<SelectionItem>),
                   typeof(SelectionBox2),
                   PropertyMetadata.Create(new CreateDefaultValueCallback(() =>
                       {
                            return new List<SelectionItem>();
                       })));


public IList<SelectionItem> SelectedItems
{
    get { return ((IList<SelectionItem>)base.GetValue(SelectedItemsProperty)); }
}

As you can see I expose the property as get-only. The issue is that this entire list can still be set by the binding system itself. In other words, while the get-only SelectedItems is 'safe' and follows conventions there is nothing to stop a call to SetValue() by the binding system which would replace the entire list. This is where WPF would have blocked this because the collection-type dependency property would be read-only.

So, what I'm asking to clarify: Should collection-types on UI classes be just regular old C# fields with a get-only property accessor? Or should they be some special-case DependencyProperty? (If so, what?)

Generally speaking I don't think SelectedItems is bindable in UWP controls anyway so this might be missing in the platform itself? If I understand correctly, your comment below indicates why binding is not supported if a new list is generated in the property getter itself. This is not a good design choice.

Generally we have the "default value" be null and then the getter returns a collection.

I should also add that I'm working on some TemplatedControls. This is a specialized case but should still be covered by the docs in my opinion.

@jevansaks
Copy link
Contributor

Ah, thank you for clarifying. @MikeHillberg, thoughts?

@jevansaks jevansaks reopened this Aug 26, 2019
@jevansaks jevansaks assigned MikeHillberg and unassigned jwmsft Aug 26, 2019
Copy link
Author

robloo commented Nov 1, 2019

@jevansaks, @MikeHillberg. This also came up in making SelectedItems bindable in a future DataGrid implementation #1500. Is there any talk of fixing this platform-wide so SelectedItems is fully bindable?

@jevansaks
Copy link
Contributor

Is there any talk of fixing this platform-wide so SelectedItems is fully bindable?

It's certainly a nice-to-have, but I don't know of a formal proposal to do so.

@robloo
Copy link
Author

robloo commented Aug 16, 2020

Created feature-request here: microsoft/microsoft-ui-xaml#3139

@jwmsft
Copy link
Contributor

jwmsft commented Sep 25, 2020

I'm closing this issue as there does not appear to be a documentation issue to address and corresponding issues have been opened in the WinUI repo.

@jwmsft jwmsft closed this as completed Sep 25, 2020
QuinnRadich pushed a commit that referenced this issue Sep 18, 2021
* Fixed some suggestions and added redirect for obsolete article

* Added some what's new
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc-enhancement feedback is about suggested additions/improvements to the article, but customer is not blocked eng-triaged platform/tech Pri2 product-question general "how do I do X" questions uwp/prod winui/tech
Projects
None yet
Development

No branches or pull requests

6 participants