C# 用户定义表单,wpf绑定控件位置

C# 用户定义表单,wpf绑定控件位置,c#,wpf,mvvm,C#,Wpf,Mvvm,我试图让用户设计自己的表单,并将控件位置保存到DB中。 现在,我能够允许用户生成新控件并在表单中移动它们。我不知道的是如何将控件的位置获取到我的Datacontext。我只能绑定宽度etd 我希望可以将canvas.left&canvas.top绑定到datacontext,但这些都没有在renderTransform上更新 有什么想法吗?谢谢你的帮助 以下是用于移动控件的返回代码: private Control _currentlyDragged; priv

我试图让用户设计自己的表单,并将控件位置保存到DB中。 现在,我能够允许用户生成新控件并在表单中移动它们。我不知道的是如何将控件的位置获取到我的Datacontext。我只能绑定宽度etd

我希望可以将canvas.left&canvas.top绑定到datacontext,但这些都没有在renderTransform上更新

有什么想法吗?谢谢你的帮助

以下是用于移动控件的返回代码:

        private Control _currentlyDragged;

        private Point _currentlyDraggedMouseOffset;

        private void Window_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (_currentlyDragged != null)
            {
                var mousePos = e.GetPosition(this);
                var futurePos = e.GetPosition(BuildCanvas);

                if (futurePos.X <= 0 || futurePos.Y <= 0 || futurePos.Y >= BuildCanvas.ActualHeight || futurePos.X >= BuildCanvas.ActualWidth)
                    return;

                _currentlyDragged.RenderTransform = new TranslateTransform(mousePos.X - _currentlyDraggedMouseOffset.X, mousePos.Y - _currentlyDraggedMouseOffset.Y);
            }
        }

        private void Window_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (_currentlyDragged != null)
                _currentlyDragged = null;

            ReleaseMouseCapture();
        }

        private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Point pt = e.GetPosition((UIElement)sender);
            _hitResultsList.Clear();

            VisualTreeHelper.HitTest(this, null, new HitTestResultCallback(MyHitTestResult), new PointHitTestParameters(pt));

            if (!_hitResultsList.Where(h => h is Border && ((Border)h).Name == "BuildCanvas").Any())
                return;

            if (_hitResultsList.Count > 0)
            {
                foreach (DependencyObject d in _hitResultsList)
                {
                    var parent = VisualTreeHelper.GetParent(d);

                    if (parent != null && (parent is Label || parent is TextBox))
                    {
                        CaptureMouse();

                        _currentlyDragged = parent as Control;

                        if (_currentlyDragged.RenderTransform is TranslateTransform)
                        {
                            _currentlyDraggedMouseOffset.X = e.GetPosition(this).X - ((TranslateTransform)_currentlyDragged.RenderTransform).X;
                            _currentlyDraggedMouseOffset.Y = e.GetPosition(this).Y - ((TranslateTransform)_currentlyDragged.RenderTransform).Y;
                        }
                        else
                        {
                            _currentlyDraggedMouseOffset.X = pt.X;
                            _currentlyDraggedMouseOffset.Y = pt.Y;
                        }
                        return;
                    }
                }
            }
            _currentlyDragged = null;
        }

        private HitTestResultBehavior MyHitTestResult(HitTestResult result)
        {
            _hitResultsList.Add(result.VisualHit);
            return HitTestResultBehavior.Continue;
        }
下面是ItemsControl:

    <Border x:Name="BuildCanvas" Grid.Column="1" Grid.Row="0" Background="#fff4c9" CornerRadius="10">
        <Grid>
            <!-- Generated controls -->
            <ItemsControl ItemsSource="{Binding TextBoxCollection}" Panel.ZIndex="1">

                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>

                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBox HorizontalAlignment="Left" VerticalAlignment="Top" Padding="2" IsEnabled="False" Background="White"
                                 Text="{Binding Name, Mode=OneWay}" Width="{Binding Width}">
                        </TextBox>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
            <!-- -->
        </Grid>
    </Border>

Rendertransform是个坏主意。每个文本框都在一个容器中

您应该绑定itemcontainer的Canvas.Top和Canvas.Left。比如:

<ItemsControl.ItemContainerStyle>
    <Style>
        <Setter Property="Canvas.Left" Value="{Binding XviewModelProperty}" />
        <Setter Property="Canvas.Top" Value="{Binding YviewModelProperty}" />
    </Style>
</ItemsControl.ItemContainerStyle>
将文本框的datacontext强制转换为viewmodel类型,并设置XviewModelProperty和YviewModelProperty


确保它们在设置时引发属性更改。

我认为rendertransform仅作为在拖动效果发生时显示拖动效果的一种方式有用。拖动完成后,您可能应该以不同的方式更新生成的位置布局变换或重新定位,但用户如何在没有rendertransform的情况下移动控件?当他们拖动时,您设置X和Y,设置canvas.Left和canvas.textbox所在容器的顶部。这会移动控件。我不明白。。。如何从窗口_PreviewMouseMove上的返回代码设置XviewModelProperty?我的意思是…控件是通过在表单的ViewModel内部的TextBoxCollection-ObservableCollection中添加项来添加的。您有一个对textbox的引用。它的datacontext是textboxviewmodel或Textboxcollection所包含的任何类型。强制转换控件的datacontext,就得到了它的viewmodel。该viewmodel具有X属性或其他属性。基本上,将其设置为鼠标的x位置,该位置由按下按钮时文本框左侧的偏移量修改。因为他们不太可能单击了控件的左上角。不要试图找出与上次移动的区别,因为如果你这样做,你的控件将跟不上。谢谢,访问datacontext并更改属性非常有效!