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 c开发者_运维知识库lass 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 itBindableInScopeItemIds
, 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.
精彩评论