简单的 ParentAdapter 实现是什么样的?

发布于 2024-07-13 06:12:55 字数 1790 浏览 4 评论 0原文

我正在尝试编写一个 ParentAdapter 实现; 我有兴趣为我正在编写的一些 WPF 控件提供设计时支持,这就是管理自定义逻辑以将项目重新设置为不同容器控件的方法。 我从小处开始,想法是创建一个 StackPanel 派生类,该类只允许 Button 元素在设计时成为父级(是的,我知道面板它本身也需要代码来支持这一点。)我从我认为最简单的 ParentAdapter 开始:

using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Windows.Design.Interaction;
using Microsoft.Windows.Design.Model;

namespace ControlLibrary.Design
{
    internal class SimplePanelParentAdapter : ParentAdapter
    {
        public override bool CanParent(ModelItem parent, Type childType)
        {
            return (childType == typeof(Button));
        }

        // moves the child item into the target panel; in this case a SimplePanel
        public override void Parent(ModelItem newParent, ModelItem child)
        {
            using (ModelEditingScope undoContext = newParent.BeginEdit())
            {
                // is this correct?
                //child.Content.SetValue("I'm in a custom panel!");
                SimplePanel pnl = newParent.GetCurrentValue() as SimplePanel;
                pnl.Children.Add(child.GetCurrentValue() as UIElement);                
                undoContext.Complete();
            }

        }

        public override void RemoveParent(ModelItem currentParent, ModelItem newParent, ModelItem child)
        {
            // No special things need to be done, right?
            child.Content.SetValue("I was in a custom panel.");
        }
    }
}

当我在设计时使用它时,只要我将一个按钮拖到上面在我的自定义面板中,VS 代码深处抛出了一个 NullReferenceException 。 我的代码没有抛出异常,因为我可以一路单步执行我的方法; 调用堆栈表明 Microsoft.Windows.Design.Developer.dll 中的代码正在引发异常。

显然我做错了一些事情,但是文档没有提供任何示例,而且我的 search-fu 似乎表明要么没有人尝试这个,要么任何尝试它的人都没有谈论它。 有人有建议吗?

I'm trying to write a ParentAdapter implementation; I'm interested in providing design-time support for some WPF controls I'm writing and this is how you manage custom logic for reparenting items to different container controls. I started small, with the notion of creating a StackPanel-derived class that would only allow Button elements to be parented at design-time (yes, I'm aware the panel itself needs code to support this as well.) I started with what I figured would be the simplest the ParentAdapter could be:

using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Windows.Design.Interaction;
using Microsoft.Windows.Design.Model;

namespace ControlLibrary.Design
{
    internal class SimplePanelParentAdapter : ParentAdapter
    {
        public override bool CanParent(ModelItem parent, Type childType)
        {
            return (childType == typeof(Button));
        }

        // moves the child item into the target panel; in this case a SimplePanel
        public override void Parent(ModelItem newParent, ModelItem child)
        {
            using (ModelEditingScope undoContext = newParent.BeginEdit())
            {
                // is this correct?
                //child.Content.SetValue("I'm in a custom panel!");
                SimplePanel pnl = newParent.GetCurrentValue() as SimplePanel;
                pnl.Children.Add(child.GetCurrentValue() as UIElement);                
                undoContext.Complete();
            }

        }

        public override void RemoveParent(ModelItem currentParent, ModelItem newParent, ModelItem child)
        {
            // No special things need to be done, right?
            child.Content.SetValue("I was in a custom panel.");
        }
    }
}

When I work with this at design-time, as soon as I drag a button over my custom panel, a NullReferenceException is thrown from deep within the VS code. My code is not throwing the exception, because I can step all the way through my method; the call stack indicates that code in Microsoft.Windows.Design.Developer.dll is throwing the exception.

Obviously I'm doing something incorrectly, but the documentation provides no examples and my search-fu seems to indicate that either no one is trying this or anyone who is trying it isn't talking about it. Does anyone have suggestions?

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

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

发布评论

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

评论(1

挽清梦 2024-07-20 06:12:55

我自己找到了问题的答案。 该问题是由编辑模型而不是 ModelItem 包装器引起的。 我应该做的(并且确实有效)是这样的:

using System;
using System.Windows.Controls;
using Microsoft.Windows.Design.Interaction;
using Microsoft.Windows.Design.Model;

namespace ControlLibrary.Design
{
    internal class SimplePanelParentAdapter : ParentAdapter
    {
        public override bool CanParent(ModelItem parent, Type childType)
        {
            return (childType == typeof(Button));
        }

        // moves the child item into the target panel; in this case a SimplePanel
        public override void Parent(ModelItem newParent, ModelItem child)
        {
            using (ModelEditingScope undoContext = newParent.BeginEdit())
            {
                ModelProperty prop = newParent.Properties["Children"];
                ModelItemCollection items = (ModelItemCollection)prop.Value;
                items.Add(child);

                undoContext.Complete();
            }

        }

        public override void RemoveParent(ModelItem currentParent, ModelItem newParent, ModelItem child)
        {
            using (ModelEditingScope scope = child.BeginEdit())
            {
                ModelProperty prop = currentParent.Properties["Children"];
                ((ModelItemCollection)prop.Value).Remove(child);

                scope.Complete();
            }
        }
    }
}

当我编写第一个代码时,我很困惑,不确定应该如何在 Children 属性上调用 Add() ; 它看起来像 ModelProperty.Value 用 ModelItemCollection 包装集合,所以除非你不遗余力地让你的类使用钝化接口,否则这应该可以工作。

I found the answer to my question myself. The problem is caused by editing the model instead of the ModelItem wrapper. What I should have done (and does work) is something like this:

using System;
using System.Windows.Controls;
using Microsoft.Windows.Design.Interaction;
using Microsoft.Windows.Design.Model;

namespace ControlLibrary.Design
{
    internal class SimplePanelParentAdapter : ParentAdapter
    {
        public override bool CanParent(ModelItem parent, Type childType)
        {
            return (childType == typeof(Button));
        }

        // moves the child item into the target panel; in this case a SimplePanel
        public override void Parent(ModelItem newParent, ModelItem child)
        {
            using (ModelEditingScope undoContext = newParent.BeginEdit())
            {
                ModelProperty prop = newParent.Properties["Children"];
                ModelItemCollection items = (ModelItemCollection)prop.Value;
                items.Add(child);

                undoContext.Complete();
            }

        }

        public override void RemoveParent(ModelItem currentParent, ModelItem newParent, ModelItem child)
        {
            using (ModelEditingScope scope = child.BeginEdit())
            {
                ModelProperty prop = currentParent.Properties["Children"];
                ((ModelItemCollection)prop.Value).Remove(child);

                scope.Complete();
            }
        }
    }
}

I was confused when I wrote the first code and unsure how I was supposed to call Add() on the Children property; it looks like ModelProperty.Value wraps collections with ModelItemCollection, so unless you go out of your way to make your class use an obtuse interface this should work.

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