WPF: Hydrate Canvas с перетаскиваемыми элементами управления во время выполнения - PullRequest
0 голосов
/ 10 февраля 2011

Вот что я пытаюсь сделать:

Я хочу иметь холст, поддерживающий перетаскивание произвольных данных в стиле Microsoft Visio.Я нашел эту ссылку, которая делает это: http://www.codeproject.com/KB/WPF/WPFDiagramDesigner_Part1.aspx

Однако я также хочу увлажнить холст во время выполнения.Я нашел этот пост: /744398/mozhno-li-svyazat-svoistvo-canvass-children-v-xaml

Одно из решений предлагает нарисовать каждый элемент на своем собственном холсте, с которым я приступил к работе.Но я не могу заставить его работать, привязывая данные к дочернему элементу 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>

Это xaml для создания и связывания моего ItemsControl на холсте.

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

1 Ответ

2 голосов
/ 10 февраля 2011

Проблема, которую я обнаружил, когда делал что-то подобное (горизонтальная перетаскиваемая временная шкала), заключалась в том, что каждый элемент был обернут в ContentPresenter до того, как он был помещен на холст, что мешало работе большого пальца. Это нормально, если вы хотите показ только для чтения, но если вы хотите перетащить это становится проблемой.

Решением было переопределить метод GetContainerForItemOverride (). Я включил свой шаблон управления, стили и XAML для самой временной шкалы.
Эта ссылка действительно помогла мне. Как изменить контейнер элементов по умолчанию для ItemsControl?

    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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...