【问题标题】:User defined form, wpf binding controls position用户自定义表单,wpf 绑定控件位置
【发布时间】:2019-08-20 08:39:03
【问题描述】:

我试图让用户设计自己的表单并将控件位置保存到数据库中。 现在,我能够允许用户生成新控件并在表单中移动它们。我不知道如何让控件的位置到我的 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>

【问题讨论】:

  • 我认为 rendertransform 仅用作在拖动效果发生时显示拖动效果的一种方式。拖动完成后,您可能应该以不同的方式更新结果位置(布局转换或重新定位)

标签: c# wpf mvvm


【解决方案1】:

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>

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

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

【讨论】:

  • 但是用户如何在没有渲染转换的情况下移动控件?
  • 当他们拖动时,您设置 X 和 Y 设置 canvas.Left 和 Canvas.Top 的容器的文本框所在的。哪个移动控件。
  • 我不明白...如何从 Window_PreviewMouseMove 的后面代码中设置 XviewModelProperty?我的意思是....通过将项目添加到 TextBoxCollection - ViewModel 中的 ObservableCollection 来添加控件。
  • 您有对文本框的引用。它的数据上下文是 textboxviewmodel 或 Textboxcollection 充满的任何类型。投射控件的数据上下文,你就有了它的视图模型。该视图模型具有 X 属性或其他属性。本质上,将其设置为鼠标按下按钮时从文本框左侧偏移修改的 x 位置。因为他们不太可能“单击”控件的左上角。不要试图找出最后一步的差异,因为如果你这样做,你的控制将跟不上。
  • 谢谢,访问数据上下文和更改属性就像一个魅力!
猜你喜欢
  • 2011-01-18
  • 2015-06-03
  • 2021-08-31
  • 2013-03-15
  • 1970-01-01
  • 2011-08-06
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多