WPF:如何从项目控件中查找数据模板中的元素

发布于 2024-08-26 16:42:41 字数 7692 浏览 4 评论 0原文

我遇到以下问题:应用程序正在使用名为 ToolBox 的自定义项目控件。工具箱的元素称为工具箱项,是自定义内容控件。现在,该工具箱存储了从数据库检索并显示的许多图像。为此,我在工具箱控件内使用数据模板。但是,当我尝试拖放元素时,我没有得到图像对象,而是得到了数据库组件。我认为我应该遍历该结构以找到 Image 元素。这是代码:

Toolbox:

public class Toolbox : ItemsControl
    {
        private Size defaultItemSize = new Size(65, 65);
        public Size DefaultItemSize
        {
            get { return this.defaultItemSize; }
            set { this.defaultItemSize = value; }
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new ToolboxItem();
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
          {
              return (item is ToolboxItem);
          }
    }

ToolBoxItem:

public class ToolboxItem : ContentControl
    {
        private Point? dragStartPoint = null;

        static ToolboxItem()
        {
            FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(ToolboxItem), new FrameworkPropertyMetadata(typeof(ToolboxItem)));
        }

        protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
        {
            base.OnPreviewMouseDown(e);
            this.dragStartPoint = new Point?(e.GetPosition(this));
        }
        public String url { get; private set; }


        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (e.LeftButton != MouseButtonState.Pressed)
            {
                this.dragStartPoint = null;
            }

            if (this.dragStartPoint.HasValue)
            {
                Point position = e.GetPosition(this);
                if ((SystemParameters.MinimumHorizontalDragDistance <=
                    Math.Abs((double)(position.X - this.dragStartPoint.Value.X))) ||
                    (SystemParameters.MinimumVerticalDragDistance <=
                    Math.Abs((double)(position.Y - this.dragStartPoint.Value.Y))))
                {
                    string xamlString = XamlWriter.Save(this.Content);



                    MessageBoxResult result = MessageBox.Show(xamlString);
                    DataObject dataObject = new DataObject("DESIGNER_ITEM", xamlString);

                    if (dataObject != null)
                    {
                        DragDrop.DoDragDrop(this, dataObject, DragDropEffects.Copy);
                    }
                }

                e.Handled = true;
            }
        }
        private childItem FindVisualChild<childItem>(DependencyObject obj)
    where childItem : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is childItem)
                    return (childItem)child;
                else
                {
                    childItem childOfChild = FindVisualChild<childItem>(child);
                    if (childOfChild != null)
                        return childOfChild;
                }
            }
            return null;
        }

    }

这是 ToolBox 和工具箱项的 xaml 文件:

    <Style TargetType="{x:Type s:ToolboxItem}">
        <Setter Property="Control.Padding"
                Value="5" />
        <Setter Property="ContentControl.HorizontalContentAlignment"
                Value="Stretch" />
        <Setter Property="ContentControl.VerticalContentAlignment"
                Value="Stretch" />
        <Setter Property="ToolTip"
                Value="{Binding ToolTip}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type s:ToolboxItem}">
                    <Grid>
                        <Rectangle Name="Border"
                                   StrokeThickness="1"
                                   StrokeDashArray="2"
                                   Fill="Transparent"
                                   SnapsToDevicePixels="true" />
                        <ContentPresenter Content="{TemplateBinding ContentControl.Content}"
                                          Margin="{TemplateBinding Padding}"
                                          SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" 
                                          ContentTemplate="{TemplateBinding ContentTemplate}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver"
                                 Value="true">
                            <Setter TargetName="Border"
                                    Property="Stroke"
                                    Value="Gray" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style TargetType="{x:Type s:Toolbox}">
        <Setter Property="SnapsToDevicePixels"
                Value="true" />
        <Setter Property="Focusable"
                Value="False" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                     <Border BorderThickness="{TemplateBinding Border.BorderThickness}"
                            Padding="{TemplateBinding Control.Padding}"
                            BorderBrush="{TemplateBinding Border.BorderBrush}"
                            Background="{TemplateBinding Panel.Background}"
                            SnapsToDevicePixels="True">
                        <ScrollViewer VerticalScrollBarVisibility="Auto">

                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />

                            </ScrollViewer>

                    </Border>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <WrapPanel Margin="0,5,0,5"
                               ItemHeight="{Binding Path=DefaultItemSize.Height, RelativeSource={RelativeSource AncestorType=s:Toolbox}}"
                               ItemWidth="{Binding Path=DefaultItemSize.Width, RelativeSource={RelativeSource AncestorType=s:Toolbox}}" />
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

用法示例:

<Toolbox x:Name="NewLibrary" DefaultItemSize="55,55" ItemsSource="{Binding}" >
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel>
                                        <Image Source="{Binding Path=url}" />
                                    </StackPanel>
                                </DataTemplate>

                        </ItemsControl.ItemTemplate>
                            </Toolbox>

我得到的对象是一个数据库对象。当使用静态资源时,我得到 Image 对象。如何从数据模板中检索此 Image 对象?我认为我可以使用本教程: http://msdn.microsoft.com/en-us/library/bb613579。 ASPX 但这似乎并不能解决问题。 有人能建议一个解决方案吗? 谢谢!

I have the following problem: the application is using the custom itemscontrol called ToolBox. The elements of a toolbox are called toolboxitems and are custom contentcontrol. Now, the toolbox stores a number of images that are retrieved from a database and displayed. For that I use a datatemplate inside the toolbox control. However, when I try to drag and drop the elements, I don't get the image object but the database component. I thought that I should then traverse the structure to find the Image element. here's the code:

Toolbox:

public class Toolbox : ItemsControl
    {
        private Size defaultItemSize = new Size(65, 65);
        public Size DefaultItemSize
        {
            get { return this.defaultItemSize; }
            set { this.defaultItemSize = value; }
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new ToolboxItem();
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
          {
              return (item is ToolboxItem);
          }
    }

ToolBoxItem:

public class ToolboxItem : ContentControl
    {
        private Point? dragStartPoint = null;

        static ToolboxItem()
        {
            FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(ToolboxItem), new FrameworkPropertyMetadata(typeof(ToolboxItem)));
        }

        protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
        {
            base.OnPreviewMouseDown(e);
            this.dragStartPoint = new Point?(e.GetPosition(this));
        }
        public String url { get; private set; }


        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (e.LeftButton != MouseButtonState.Pressed)
            {
                this.dragStartPoint = null;
            }

            if (this.dragStartPoint.HasValue)
            {
                Point position = e.GetPosition(this);
                if ((SystemParameters.MinimumHorizontalDragDistance <=
                    Math.Abs((double)(position.X - this.dragStartPoint.Value.X))) ||
                    (SystemParameters.MinimumVerticalDragDistance <=
                    Math.Abs((double)(position.Y - this.dragStartPoint.Value.Y))))
                {
                    string xamlString = XamlWriter.Save(this.Content);



                    MessageBoxResult result = MessageBox.Show(xamlString);
                    DataObject dataObject = new DataObject("DESIGNER_ITEM", xamlString);

                    if (dataObject != null)
                    {
                        DragDrop.DoDragDrop(this, dataObject, DragDropEffects.Copy);
                    }
                }

                e.Handled = true;
            }
        }
        private childItem FindVisualChild<childItem>(DependencyObject obj)
    where childItem : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is childItem)
                    return (childItem)child;
                else
                {
                    childItem childOfChild = FindVisualChild<childItem>(child);
                    if (childOfChild != null)
                        return childOfChild;
                }
            }
            return null;
        }

    }

here is the xaml file for ToolBox and toolbox item:

    <Style TargetType="{x:Type s:ToolboxItem}">
        <Setter Property="Control.Padding"
                Value="5" />
        <Setter Property="ContentControl.HorizontalContentAlignment"
                Value="Stretch" />
        <Setter Property="ContentControl.VerticalContentAlignment"
                Value="Stretch" />
        <Setter Property="ToolTip"
                Value="{Binding ToolTip}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type s:ToolboxItem}">
                    <Grid>
                        <Rectangle Name="Border"
                                   StrokeThickness="1"
                                   StrokeDashArray="2"
                                   Fill="Transparent"
                                   SnapsToDevicePixels="true" />
                        <ContentPresenter Content="{TemplateBinding ContentControl.Content}"
                                          Margin="{TemplateBinding Padding}"
                                          SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" 
                                          ContentTemplate="{TemplateBinding ContentTemplate}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver"
                                 Value="true">
                            <Setter TargetName="Border"
                                    Property="Stroke"
                                    Value="Gray" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style TargetType="{x:Type s:Toolbox}">
        <Setter Property="SnapsToDevicePixels"
                Value="true" />
        <Setter Property="Focusable"
                Value="False" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                     <Border BorderThickness="{TemplateBinding Border.BorderThickness}"
                            Padding="{TemplateBinding Control.Padding}"
                            BorderBrush="{TemplateBinding Border.BorderBrush}"
                            Background="{TemplateBinding Panel.Background}"
                            SnapsToDevicePixels="True">
                        <ScrollViewer VerticalScrollBarVisibility="Auto">

                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />

                            </ScrollViewer>

                    </Border>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <WrapPanel Margin="0,5,0,5"
                               ItemHeight="{Binding Path=DefaultItemSize.Height, RelativeSource={RelativeSource AncestorType=s:Toolbox}}"
                               ItemWidth="{Binding Path=DefaultItemSize.Width, RelativeSource={RelativeSource AncestorType=s:Toolbox}}" />
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

Example usage:

<Toolbox x:Name="NewLibrary" DefaultItemSize="55,55" ItemsSource="{Binding}" >
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel>
                                        <Image Source="{Binding Path=url}" />
                                    </StackPanel>
                                </DataTemplate>

                        </ItemsControl.ItemTemplate>
                            </Toolbox>

The object that I get is a database object. When using a static resource I get the Image object. How to retrieve this Image object from a datatemplate? I though that I could use this tutorial:
http://msdn.microsoft.com/en-us/library/bb613579.aspx
But it does not seem to solve the problem.
Could anyone suggest a solution?
Thanks!

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

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

发布评论

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

评论(1

墨落成白 2024-09-02 16:42:41

在 ToolboxItem 的代码隐藏中,调用像他这样的方法:

FindVisualChild<Image>(this);

这对我来说效果很好,并返回我预期的图像对象。

In Code Behind of ToolboxItem call the method like his:

FindVisualChild<Image>(this);

This works fine for me and returns me the expected Image Object.

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