WPF 行为和事件 - 附加到适当的事件
WPF behaviors and events - attaching to proper events
我这里有一个处理拖放的行为,我通过视图附加了鼠标事件。项目的视图模型继承自 IDraggable
。我使用 Caliburn.Micro 作为 MVVM 框架。
<ItemsControl x:Name="Items">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=X}" />
<Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
<Setter Property="Width" Value="{Binding Path=Width}" />
<Setter Property="Height" Value="{Binding Path=Height}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border>
<!-- item contents -->
<i:Interaction.Behaviors>
<behaviors:DragOnCanvasBehavior DraggableItem="{Binding}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseLeftButtonDown">
<i:InvokeCommandAction CommandName="StartDrag" />
</i:EventTrigger>
<i:EventTrigger EventName="PreviewMouseLeftButtonUp">
<i:InvokeCommandAction CommandName="StopDrag" />
</i:EventTrigger>
<i:EventTrigger EventName="PreviewMouseMove">
<i:InvokeCommandAction CommandName="Dragging" />
</i:EventTrigger>
</i:Interaction.Triggers>
</behaviors:DragOnCanvasBehavior>
</i:Interaction.Behaviors>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
然后行为将鼠标事件附加到元素的鼠标处理程序:
public class DragOnCanvasBehavior : Behavior<DependencyObject>
{
public static readonly DependencyProperty DraggableItemProperty =
DependencyProperty.RegisterAttached(
"DraggableItem",
typeof(IDraggable),
typeof(DragOnCanvasBehavior),
new PropertyMetadata(new PropertyChangedCallback((d, e) =>
{
((DragOnCanvasBehavior)d).draggable = (IDraggable)e.NewValue;
})));
private IDraggable draggable;
public DragOnCanvasBehavior()
{
this.StartDrag = new RelayCommand((o) =>
{
((UIElement)this.AssociatedObject).MouseLeftButtonDown += this.ElementOnMouseLeftButtonDown;
});
this.StopDrag = new RelayCommand((o) =>
{
((UIElement)this.AssociatedObject).MouseLeftButtonUp += this.ElementOnMouseLeftButtonUp;
});
this.Dragging = new RelayCommand((o) =>
{
((UIElement)this.AssociatedObject).MouseMove += this.ElementOnMouseMove;
});
}
public IDraggable DraggableItem
{
get { return (IDraggable)this.GetValue(DraggableItemProperty); }
set { this.SetValue(DraggableItemProperty, value); }
}
public ICommand Dragging { get; private set; }
public ICommand StartDrag { get; private set; }
public ICommand StopDrag { get; private set; }
// these handle the drag through the IDraggable properties
// and the mouse event args
private void ElementOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {}
private void ElementOnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) {}
private void ElementOnMouseMove(object sender, MouseEventArgs e) {}
}
它有效,但我很确定我在这里做错了什么。鼠标事件附加在行为构造函数中,但它们是 "hard-linked" 事件(这意味着我无法将触发器更改为 mousedown/up/move 以外的其他内容)。
但是,我必须能够访问 ElementOnMousexxx
方法中的鼠标位置,所以我不确定如何正确执行此操作。
好的,事实证明您不需要 MouseEventArgs
来获取鼠标光标位置,您可以只使用 System.Windows.Input.Mouse
。您也不需要 "sender" 对象,当使用 Behavior<T>
时,您可以只使用 this.AssociatedObject
public DragOnCanvasBehavior()
{
this.StartDrag = new RelayCommand((o) =>
{
this.OnStartDrag();
});
}
private void OnStartDrag()
{
// get mouse position
this.mouseStartPosition = Mouse.GetPosition(Application.Current.MainWindow);
// access control properties
((UIElement)this.AssociatedObject).CaptureMouse();
}
我这里有一个处理拖放的行为,我通过视图附加了鼠标事件。项目的视图模型继承自 IDraggable
。我使用 Caliburn.Micro 作为 MVVM 框架。
<ItemsControl x:Name="Items">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=X}" />
<Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
<Setter Property="Width" Value="{Binding Path=Width}" />
<Setter Property="Height" Value="{Binding Path=Height}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border>
<!-- item contents -->
<i:Interaction.Behaviors>
<behaviors:DragOnCanvasBehavior DraggableItem="{Binding}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseLeftButtonDown">
<i:InvokeCommandAction CommandName="StartDrag" />
</i:EventTrigger>
<i:EventTrigger EventName="PreviewMouseLeftButtonUp">
<i:InvokeCommandAction CommandName="StopDrag" />
</i:EventTrigger>
<i:EventTrigger EventName="PreviewMouseMove">
<i:InvokeCommandAction CommandName="Dragging" />
</i:EventTrigger>
</i:Interaction.Triggers>
</behaviors:DragOnCanvasBehavior>
</i:Interaction.Behaviors>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
然后行为将鼠标事件附加到元素的鼠标处理程序:
public class DragOnCanvasBehavior : Behavior<DependencyObject>
{
public static readonly DependencyProperty DraggableItemProperty =
DependencyProperty.RegisterAttached(
"DraggableItem",
typeof(IDraggable),
typeof(DragOnCanvasBehavior),
new PropertyMetadata(new PropertyChangedCallback((d, e) =>
{
((DragOnCanvasBehavior)d).draggable = (IDraggable)e.NewValue;
})));
private IDraggable draggable;
public DragOnCanvasBehavior()
{
this.StartDrag = new RelayCommand((o) =>
{
((UIElement)this.AssociatedObject).MouseLeftButtonDown += this.ElementOnMouseLeftButtonDown;
});
this.StopDrag = new RelayCommand((o) =>
{
((UIElement)this.AssociatedObject).MouseLeftButtonUp += this.ElementOnMouseLeftButtonUp;
});
this.Dragging = new RelayCommand((o) =>
{
((UIElement)this.AssociatedObject).MouseMove += this.ElementOnMouseMove;
});
}
public IDraggable DraggableItem
{
get { return (IDraggable)this.GetValue(DraggableItemProperty); }
set { this.SetValue(DraggableItemProperty, value); }
}
public ICommand Dragging { get; private set; }
public ICommand StartDrag { get; private set; }
public ICommand StopDrag { get; private set; }
// these handle the drag through the IDraggable properties
// and the mouse event args
private void ElementOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {}
private void ElementOnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) {}
private void ElementOnMouseMove(object sender, MouseEventArgs e) {}
}
它有效,但我很确定我在这里做错了什么。鼠标事件附加在行为构造函数中,但它们是 "hard-linked" 事件(这意味着我无法将触发器更改为 mousedown/up/move 以外的其他内容)。
但是,我必须能够访问 ElementOnMousexxx
方法中的鼠标位置,所以我不确定如何正确执行此操作。
好的,事实证明您不需要 MouseEventArgs
来获取鼠标光标位置,您可以只使用 System.Windows.Input.Mouse
。您也不需要 "sender" 对象,当使用 Behavior<T>
时,您可以只使用 this.AssociatedObject
public DragOnCanvasBehavior()
{
this.StartDrag = new RelayCommand((o) =>
{
this.OnStartDrag();
});
}
private void OnStartDrag()
{
// get mouse position
this.mouseStartPosition = Mouse.GetPosition(Application.Current.MainWindow);
// access control properties
((UIElement)this.AssociatedObject).CaptureMouse();
}