扩展 MVVM 的现有控件

发布于 2024-10-29 12:35:50 字数 329 浏览 6 评论 0原文

我正在尝试扩展一个名为 PivotViewer 的现有 Microsoft 控件。

该控件有一个现有属性,我想将其公开给我的 ViewModel。

public ICollection<string> InScopeItemIds { get; }

我创建了一个名为 CustomPivotViewer 的继承类,并且想要创建一个可以绑定的依赖属性,该属性将公开基类中 InScopeItemIds 中保存的值。

我花了很长时间阅读有关 DependencyPropertys 的内容,但我变得非常沮丧。

这可能吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

要走就滚别墨迹 2024-11-05 12:35:50

如果您希望可绑定,则只需要一个DependencyProperty,这意味着:例如,如果您想在您的应用程序中拥有MyBindableProperty属性,控件,您希望能够使用它来执行操作:

MyBindableProperty={Binding SomeProperty}

但是,如果您希望其他DependencyProperties绑定到它,则任何属性(无论是可以使用 DependencyProperty 或普通的 DependencyProperty。

我不确定你真正需要什么,也许你可以澄清更多,但如果这是你想要实现的第一个场景,你可以按如下方式执行:

  • 创建一个DependencyProperty,让我们将其命名为 BindableInScopeItemIds,如下所示:

    /// <摘要>
    /// BindableInScopeItemIds 依赖属性
    /// 
    公共静态只读 DependencyProperty BindableInScopeItemIdsProperty =
        DependencyProperty.Register("BindableInScopeItemIds", typeof(ICollection), typeof(CustomPivotViewer),
            新的属性元数据(空,
                新的 PropertyChangedCallback(OnBindableInScopeItemIdsChanged)));
    
    /// <摘要>
    /// 获取或设置 BindableInScopeItemIds 属性。这个依赖属性 
    /// 表示....
    /// 
    公共 ICollection; BindableInScopeItemIds
    {
        获取 { return (ICollection)GetValue(BindableInScopeItemIdsProperty); }
        设置 { SetValue(BindableInScopeItemIdsProperty, 值); }
    }
    
    /// <摘要>
    /// 处理对 BindableInScopeItemIds 属性的更改。
    /// 
    私有静态无效OnBindableInScopeItemIdsChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
    {
        var target = (CustomPivotViewer)d;
        ICollection<字符串> oldBindableInScopeItemIds = (ICollection)e.OldValue;
        ICollection<字符串> newBindableInScopeItemIds = target.BindableInScopeItemIds;
        target.OnBindableInScopeItemIdsChanged(oldBindableInScopeItemIds, newBindableInScopeItemIds);
    }
    
    /// <摘要>
    /// 为派生类提供处理 BindableInScopeItemIds 属性更改的机会。
    /// 
    protected virtual void OnBindableInScopeItemIdsChanged(ICollection oldBindableInScopeItemIds, ICollection newBindableInScopeItemIds)
    {
    }
    
  • OnBindableInScopeItemIdsChanged中,您可以更新内部集合 (InScopeItemIds)

请记住您的属性想要公开的是只读(它没有“setter”),因此您可能需要这样更新:

protected virtual void OnBindableInScopeItemIdsChanged(ICollection<string> oldBindableInScopeItemIds, ICollection<string> newBindableInScopeItemIds)
{
    InScopeItemIds.Clear();
    foreach (var itemId in newBindableInScopeItemIds)
    {
        InScopeItemIds.Add(itemId);
    }
}

希望这会有所帮助:)

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

ゃ人海孤独症 2024-11-05 12:35:50

编辑

我意识到了误解,这是一个新版本(在原始问题的上下文中):

因此,您可以使用绑定所需的属性,并考虑以下情况:

  • 因为这样属性是只读的,您将无法将其用于双向绑定。
  • 只要包含类型未实现 INotifyPropertyChanged,用于显示数据的目标控件将不会收到有关属性值更改的通知。
  • 只要此属性值返回的值未实现 INotifyCollectionChanged(一个示例是 ObservableCollection),对集合的更改将不会影响用于显示它的目标控件。

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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文