首页 > 解决方案 > 用户自定义表单,wpf 绑定控件位置

问题描述

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

我希望我可以将 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>

标签: c#wpfmvvm

解决方案


渲染转换是一个坏主意。每个文本框都在一个容器中。

您应该绑定 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>

将文本框的数据上下文转换为任何视图模型类型并设置 XviewModelProperty 和 YviewModelProperty。

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


推荐阅读