我想在運行時通過其控制點 Q(Segment 的 Point1 屬性)控制
目前沒有任何代碼,我試圖將所有內容都保存在 XAML/MVVM 中,但不確定這是否可能。謝謝。
這是視圖模型:
namespace BezierDemo
{
class MainViewModel : INotifyPropertyChanged
{
private System.Windows.Point _q;
private double _qy;
private double _qx;
public MainViewModel()
{
_q.X = 50;
_q.Y = 0;
}
// https://www.danrigby.com/2015/09/12/inotifypropertychanged-the-net-4-6-way/
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
{
return false;
}
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
public double QX
{
get { return _q.X; }
set { Q = new System.Windows.Point(value, Q.Y); SetProperty(ref this._qx, value); }
}
public double QY
{
get { return _q.Y; }
set { Q = new System.Windows.Point(Q.X, value); SetProperty(ref this._qy, value); }
}
public System.Windows.Point Q
{
get { return _q; }
set { SetProperty(ref this._q, value); }
}
}
}
...這是XAML:
<Window x:Class="BezierDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BezierDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="506">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400*"/>
<ColumnDefinition Width="100*"/>
</Grid.ColumnDefinitions>
<!-- Bezier Control Point -->
<Canvas Grid.Column="0">
<Ellipse Width="5" Height="5" Fill="Indigo" Stroke="Indigo" Cursor="Hand" >
<Ellipse.RenderTransform>
<TranslateTransform X="{Binding Path=QX}" Y="{Binding Path=QY}"/>
</Ellipse.RenderTransform>
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Ellipse.MouseMove">
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
</Canvas>
<!-- QuadraticBezierSegment -->
<Path Stroke="Black" Fill="Gray" Grid.Column="0">
<Path.Data>
<PathGeometry>
<PathFigure>
<PathFigure.StartPoint>
<Point X="0" Y="100" />
</PathFigure.StartPoint>
<QuadraticBezierSegment Point1="{Binding Path=Q}" Point2="100, 100" />
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
<!-- X & Y Slider Controls -->
<Grid Grid.Column="2" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<Slider Name="X" Orientation="Vertical" Maximum="100" HorizontalAlignment="Center" VerticalAlignment="Center" Height="234" Value="{Binding Path=QX}" Minimum="0.0"/>
<Label HorizontalAlignment="Center">X</Label>
</StackPanel>
<StackPanel Grid.Column="1" VerticalAlignment="Center">
<Slider Name="Y" Orientation="Vertical" Maximum="100" HorizontalAlignment="Center" VerticalAlignment="Center" Height="234" Value="{Binding Path=QY}" Minimum="0.0"/>
<Label HorizontalAlignment="Center">Y</Label>
</StackPanel>
</Grid>
</Grid>
uj5u.com熱心網友回復:
如果您將 Bezier 控制點包裝在一個Thumb元素中,那么您可以很容易地完成您想要的操作。
<!-- Bezier Control Point -->
<Canvas Grid.Column="0">
<Thumb DragDelta="Thumb_DragDelta" Canvas.Left="{Binding QX, Mode=TwoWay}" Canvas.Top="{Binding QY, Mode=TwoWay}">
<Thumb.Template>
<ControlTemplate>
<Ellipse Width="5" Height="5" Fill="Indigo" Stroke="Indigo" />
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Canvas>
注意:我必須添加Panel.ZIndex="-1"到 QuadraticBezierSegment 以便橢圓會在 Bezier 段之前呈現。或者您可以在貝塞爾曲線段宣告之后移動拇指部分。
代碼隱藏:
private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
UIElement thumb = e.Source as UIElement;
Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) e.HorizontalChange);
Canvas.SetTop(thumb, Canvas.GetTop(thumb) e.VerticalChange);
}
您可以使用Microsoft.Xaml.Behaviors.Wpf nuget 包將后面的代碼轉換為視圖模型中的事件處理程式。
看起來像這樣
<Canvas Grid.Column="0">
<Thumb Canvas.Left="{Binding QX, Mode=TwoWay}" Canvas.Top="{Binding QY, Mode=TwoWay}">
<b:Interaction.Triggers>
<b:EventTrigger EventName="DragDelta">
<b:InvokeCommandAction Command="{Binding HandleDragDelta}" PassEventArgsToCommand="True" />
</b:EventTrigger>
</b:Interaction.Triggers>
<Thumb.Template>
<ControlTemplate>
<Ellipse Width="5" Height="5" Fill="Indigo" Stroke="Indigo" />
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Canvas>
哪里HandleDragDelta是某種ICommand可以采用DragDeltaEventArgs引數的實作,因為您將需要它。
private DelegateCommand<DragDeltaEventArgs> handleDragDelta;
public ICommand HandleDragDelta => handleDragDelta ??= new DelegateCommand<DragDeltaEventArgs>(PerformHandleDragDelta);
private void PerformHandleDragDelta(DragDeltaEventArgs e)
{
UIElement thumb = e.Source as UIElement;
Canvas.SetLeft(thumb, Canvas.GetLeft(thumb) e.HorizontalChange);
Canvas.SetTop(thumb, Canvas.GetTop(thumb) e.VerticalChange);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/360482.html
