WPF基于MVVM Binding实现边框内矩形拖拽移动与宽度调整咨询
实现方案
前置调整
你当前用StackPanel作为ItemsPanel无法支持元素的自由定位,首先要做基础改造:
- 给你的条目ViewModel添加
OffsetX属性(代表矩形在容器内的左侧偏移量),和已有的Duration属性都实现INotifyPropertyChanged接口,支持双向绑定通知。 - 把ItemsControl的布局容器从StackPanel替换为Canvas,代码如下:
<ItemsControl.ItemsPanel> <ItemsPanelTemplate> <Canvas x:Name="CanvasN" Margin="0 2" Background="Transparent"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel>
- 给ItemsControl添加ItemContainerStyle,绑定每个条目的左侧位置:
<ItemsControl.ItemContainerStyle> <Style TargetType="ContentPresenter"> <Setter Property="Canvas.Left" Value="{Binding OffsetX, Mode=TwoWay}"/> </Style> </ItemsControl.ItemContainerStyle>
问题1:矩形左右拖拽移动实现
给rectOuter添加鼠标事件处理逻辑,也可以封装为附加属性/Behavior适配MVVM规范:
- 鼠标左键按下时:记录当前鼠标坐标、对应条目的原始
OffsetX值,标记进入拖拽状态 - 鼠标移动时:如果处于拖拽状态,计算当前鼠标和按下时的水平偏移差,将差值加到原始
OffsetX上更新属性;同时做边界限制:OffsetX不能小于0,也不能大于「容器总宽度 - 当前矩形宽度」,避免拖出边框外 - 鼠标左键松开时:清除拖拽状态标记
问题2:右边缘拖拽调整宽度实现
首先在条目模板的gridElement内添加右侧拖拽手柄,代码如下:
<Grid x:Name="gridElement" Width="{Binding Duration, Mode=TwoWay}"> <Rectangle x:Name="rectOuter" Fill="Blue" Opacity=".3" /> <!-- 右侧透明拖拽手柄,鼠标悬停会显示左右调整光标 --> <Rectangle x:Name="resizeHandle" Width="4" HorizontalAlignment="Right" Background="Transparent" Cursor="SizeWE"/> <Grid HorizontalAlignment="Center"> <TextBlock x:Name="txt2" Text="{Binding Title}" HorizontalAlignment="Stretch"/> </Grid> </Grid>
然后给resizeHandle添加鼠标事件逻辑:
- 鼠标左键按下时:记录当前鼠标坐标、对应条目的原始
Duration值,标记进入宽度调整状态 - 鼠标移动时:如果处于宽度调整状态,计算当前鼠标和按下时的水平偏移差,将差值加到原始
Duration上更新属性;同时做边界限制:Duration最小不能小于你设定的最小值(比如10,避免矩形缩到看不见),最大不能超过「容器总宽度 - 当前OffsetX」,避免调整后超出边框 - 鼠标左键松开时:清除宽度调整状态标记
如果需要完全符合无后台代码的MVVM规范,可以把上述拖拽、调整宽度的逻辑封装为附加属性,或者引入Microsoft.Xaml.Behaviors.Wpf包封装为Behavior,绑定到ViewModel的对应命令即可。
内容的提问来源于stack exchange,提问作者nqt95
相关产品推荐
相关产品推荐

