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.");
        }
    }
}

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

显然我做错了什么,但文档没有提供任何示例,我的 search-fu 似乎表明没有人在尝试这个,或者任何尝试它的人都没有谈论它。有人有建议吗?

4

1 回答 1

0

我自己找到了我的问题的答案。该问题是由编辑模型而不是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 包装了集合,所以除非你不遗余力地让你的类使用钝接口,否则它应该可以工作。

于 2009-02-03T20:24:05.290 回答