Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF:运行时具有可拖动控件的画布_C#_Wpf_Mvvm_Wpf Controls_Binding - Fatal编程技术网

C# WPF:运行时具有可拖动控件的画布

C# WPF:运行时具有可拖动控件的画布,c#,wpf,mvvm,wpf-controls,binding,C#,Wpf,Mvvm,Wpf Controls,Binding,这就是我试图实现的目标: 我想要一个画布,支持以Microsoft Visio的样式拖放任意数据。我找到了这样的链接: 但是,我还希望在运行时为画布添加水分。我发现这个帖子: 其中一个解决方案建议在自己的画布上绘制每个项目,我已经开始工作了。但我无法通过将数据绑定到画布的ItemControl子级来让它拖放工作。理想情况下,我希望避免使用代码隐藏来实现这一点。是否有一个XAML解决方案使用我所有的东西?我的代码如下: 这是我创建的MoveThumb,它是实际移动的控件 class MoveTh

这就是我试图实现的目标:

我想要一个画布,支持以Microsoft Visio的样式拖放任意数据。我找到了这样的链接:

但是,我还希望在运行时为画布添加水分。我发现这个帖子:

其中一个解决方案建议在自己的画布上绘制每个项目,我已经开始工作了。但我无法通过将数据绑定到画布的ItemControl子级来让它拖放工作。理想情况下,我希望避免使用代码隐藏来实现这一点。是否有一个XAML解决方案使用我所有的东西?我的代码如下:

这是我创建的MoveThumb,它是实际移动的控件

class MoveThumb : Thumb
    {
        public MoveThumb()
        {
            DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta);
        }

        private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Control item = this.DataContext as Control;

            if (item != null)
            {
                double left = Canvas.GetLeft(item);
                double top = Canvas.GetTop(item);

                Canvas.SetLeft(item, left + e.HorizontalChange);
                Canvas.SetTop(item, top + e.VerticalChange);                
            }
        }
    }
这是我在第一个链接中定义的xaml模板

<ControlTemplate x:Key="MoveThumbTemplate" TargetType="{x:Type t:MoveThumb}">
            <Rectangle Fill="Gray"/>
        </ControlTemplate>


        <ControlTemplate x:Key="NodeItemTemplate">
            <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                <t:MoveThumb Template="{StaticResource MoveThumbTemplate}"
                Cursor="SizeAll"/>
                <ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
            </Grid>
        </ControlTemplate>

        <DataTemplate x:Key="nodeTemplate" DataType="Node">            
                <ContentControl Name="NodeItem"
                                Width="50"
                                Height="50"
                                Canvas.Top="50"
                                Canvas.Left="50"
                                Template="{StaticResource NodeItemTemplate}">
                    <Ellipse Fill="Black" IsHitTestVisible="False"/>
                </ContentControl>            
        </DataTemplate>

这是在画布中创建和绑定my ItemsControl的xaml

 <ItemsControl ItemsSource="{Binding Path=NodeCollection}" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas Background="Yellow" Width="auto" Height="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>

                    <DataTemplate>
                        <ContentControl Name="NodeItem"
                                Width="50"
                                Height="50"
                                Canvas.Top="100"
                                Canvas.Left="100"
                                Template="{StaticResource NodeItemTemplate}">
                            <Ellipse Fill="Black" IsHitTestVisible="False"/>
                        </ContentControl>
                    </DataTemplate>

                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemContainerStyle>
                    <Style>
                        <Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
                        <Setter Property="Canvas.Left" Value="{Binding Path=X}" />
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>

我在做类似的事情(水平可拖动时间线)时发现的问题是,每个项目在放在画布上之前都被包装在ContentPresenter中,这使拇指无法工作。如果您想要一个只读显示,它是可以的,但是如果您想要拖动它,它就会成为一个问题

解决方案是重写GetContainerForItemOverride()方法。我已经包括了我的控件模板、样式和时间轴本身的XAML
这个链接真的帮助了我

公共类时间线:ItemsControl
{
受保护的覆盖System.Windows.DependencyObject GetContainerForItemOverride()
{
返回新的ContentControl();
}
受保护的覆盖无效PrepareContainerForItemOverride(System.Windows.DependencyObject元素,对象项)
{
var控制=作为控制的元素;
if(控件!=null)
{
var myUri=newURI(“/ResourceDictionary.xaml”,UriKind.Relative);
var dictionary=Application.LoadComponent(myUri)作为ResourceDictionary;
如果(字典!=null)
{
control.Template=(ControlTemplate)字典[“TimelineElementTemplate”];
}
control.DataContext=item;
}
base.PrepareContainerForItemOverride(元素、项);
}
}

谢谢您的帮助。我还发现了这个可拖动的画布[这就是我希望它做的一些事情。我可能会将您的答案与我找到的链接结合起来,编写某种自定义控件。谢谢您的帮助。由于我现在遇到了完全相同的问题,您能否使示例更加完整?您能否包括
帮助类
-我假设这些是
附件属性
。谢谢您的时间。@Vish您能分享您的完整解决方案吗?@MoonKnight我已经从档案中找到了这个项目:)如何才能最好地把它交给您?@JohnPetrak非常感谢您。您能把文件放在这里吗:?
    public class Timeline : ItemsControl
        {
            protected override System.Windows.DependencyObject GetContainerForItemOverride()
            {
                return new ContentControl();
            }

            protected override void PrepareContainerForItemOverride(System.Windows.DependencyObject element, object item)
            {
                var control = element as Control;
                if (control != null)
                {
                    var myUri = new Uri("/ResourceDictionary.xaml", UriKind.Relative);
                    var dictionary = Application.LoadComponent(myUri) as ResourceDictionary;

                    if (dictionary != null)
                    {
                        control.Template = (ControlTemplate)dictionary["TimelineElementTemplate"];
                    }

                    control.DataContext = item;
                }
                base.PrepareContainerForItemOverride(element, item);
            }
        }


        <ControlTemplate x:Key="TimelineElementTemplate" TargetType="{x:Type Controls:ContentControl}">
                <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
                    <TextBlock Text="{Binding Path=DataContext.DebugData}"                        
                               ToolTip="{Binding Path=DataContext.DebugData}"
                               Background="{Binding Path=DataContext.Background}"/>
                    <Control Template="{StaticResource ResizeDecoratorTemplate}" />            
                </Grid>
            </ControlTemplate>

    <Style x:Key="TimelineElementStyle" TargetType="Controls:ContentControl">
        <Setter Property="Canvas.Left">
            <Setter.Value>
                <Binding Path="LeftPos" Mode="TwoWay"/>
            </Setter.Value>
        </Setter>

        <Setter Property="Width">
            <Setter.Value>
                <Binding Path="Width" Mode="TwoWay"/>
            </Setter.Value>
        </Setter>         
    </Style>

<Style x:Key="TimelineStyle" TargetType="ItemsControl">
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <Canvas Background="LightGray"></Canvas>
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
</Style>


    <Controls:Timeline Style="{StaticResource TimelineStyle}" 
                               DataContext="{StaticResource timelineViewModel}"   
                               ItemContainerStyle="{StaticResource TimelineElementStyle}"
                               ItemsSource="{Binding ListOfTimelineElements}"
                               HelperClasses:DragDropHelper.IsDragSource="False" 
                               HelperClasses:DragDropHelper.IsDropTarget="True" 
                               HelperClasses:SizeObserver.Observe="True"                 
                               HelperClasses:SizeObserver.ObservedWidth="{Binding TotalWidth, Mode=OneWayToSource}" 
                               BorderBrush="Black" 
                               BorderThickness="1">

            </Controls:Timeline>