C# 在MVVM中处理MouseEnter over命令
我有一个带有ItemControl的画布,填充在带有自定义UserControlViewModels的ViewModel中。我想给每个用户控件一个MouseEnter命令之类的东西 我的ViewModel的XAML如下所示:C# 在MVVM中处理MouseEnter over命令,c#,wpf,xaml,mvvm,command,C#,Wpf,Xaml,Mvvm,Command,我有一个带有ItemControl的画布,填充在带有自定义UserControlViewModels的ViewModel中。我想给每个用户控件一个MouseEnter命令之类的东西 我的ViewModel的XAML如下所示: <Canvas x:Name="gameFieldCanvas" Width="{Binding CanvasWidth}" Height="{Binding CanvasHeight}"> <ItemsControl ItemsSource="{B
<Canvas x:Name="gameFieldCanvas" Width="{Binding CanvasWidth}" Height="{Binding CanvasHeight}">
<ItemsControl ItemsSource="{Binding GameFieldContent}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:GameFieldTileViewModel}">
<Canvas>
<local:GameFieldTileUserControl X="{Binding TileX}" Y="{Binding TileY}">
<local:GameFieldTileUserControl.InputBindings>
<MouseBinding MouseAction="LeftClick"
Command="{Binding DataContext.OnGameFieldTileLeftClicked, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"/>
<MouseBinding MouseAction="RightClick" Command="{Binding DataContext.OnGameFieldTileRightClicked, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding}"/>
</local:GameFieldTileUserControl.InputBindings>
</local:GameFieldTileUserControl>
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Canvas>
就像你可以看到的,我已经用左键/右键点击这个命令了。但是mouseenterements没有输入绑定
我已经读过关于Blend SDK的文章,在那里你可以编写EventTriggers或者类似的东西,但是这不可能用board工具吗
我只想知道当输入一个UserControl时,如何获取它的UserControlViewModel。你能告诉我你最后想要完成什么吗?我可能有一个更好的答案给你,这取决于你,但你可以,我有很多次,覆盖现有的控制和添加命令属性需要 这是一个自定义用户控件,它具有鼠标移动命令
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WPF_Question_Answer_App
{
public partial class MouseMoveCommandUserControl : UserControl
{
public MouseMoveCommandUserControl()
{
InitializeComponent();
MouseMove += (s, e) =>
{
if (MouseMoveCommand?.CanExecute(MouseMoveCommandParameter) ?? false)
MouseMoveCommand.Execute(MouseMoveCommandParameter);
};
}
public ICommand MouseMoveCommand
{
get => (ICommand)GetValue(MouseMoveCommandProperty);
set => SetValue(MouseMoveCommandProperty, value);
}
public static readonly DependencyProperty MouseMoveCommandProperty =
DependencyProperty.Register(nameof(MouseMoveCommand), typeof(ICommand), typeof(MouseMoveCommandUserControl), new PropertyMetadata(null));
public object MouseMoveCommandParameter
{
get => GetValue(MouseMoveCommandParameterProperty);
set => SetValue(MouseMoveCommandParameterProperty, value);
}
public static readonly DependencyProperty MouseMoveCommandParameterProperty =
DependencyProperty.Register(nameof(MouseMoveCommandParameter), typeof(object), typeof(MouseMoveCommandUserControl), new PropertyMetadata(null));
}
}
这是在视图中使用的,这是显而易见的
<Window x:Class="WPF_Question_Answer_App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_Question_Answer_App"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:MouseMoveCommandUserControl MouseMoveCommand="{Binding SomeMouseMoveCommand}"
MouseMoveCommandParameter="{Binding SomeMouseMoveCommandParameter}"/>
</Grid>
</Window>
希望这有助于。。。如果没有,我会删除答案,请告诉我。你能详细告诉我你最后想要完成什么吗?我可能有一个更好的答案给你,这取决于你,但你可以,我有很多次,覆盖现有的控制和添加命令属性需要 这是一个自定义用户控件,它具有鼠标移动命令
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WPF_Question_Answer_App
{
public partial class MouseMoveCommandUserControl : UserControl
{
public MouseMoveCommandUserControl()
{
InitializeComponent();
MouseMove += (s, e) =>
{
if (MouseMoveCommand?.CanExecute(MouseMoveCommandParameter) ?? false)
MouseMoveCommand.Execute(MouseMoveCommandParameter);
};
}
public ICommand MouseMoveCommand
{
get => (ICommand)GetValue(MouseMoveCommandProperty);
set => SetValue(MouseMoveCommandProperty, value);
}
public static readonly DependencyProperty MouseMoveCommandProperty =
DependencyProperty.Register(nameof(MouseMoveCommand), typeof(ICommand), typeof(MouseMoveCommandUserControl), new PropertyMetadata(null));
public object MouseMoveCommandParameter
{
get => GetValue(MouseMoveCommandParameterProperty);
set => SetValue(MouseMoveCommandParameterProperty, value);
}
public static readonly DependencyProperty MouseMoveCommandParameterProperty =
DependencyProperty.Register(nameof(MouseMoveCommandParameter), typeof(object), typeof(MouseMoveCommandUserControl), new PropertyMetadata(null));
}
}
这是在视图中使用的,这是显而易见的
<Window x:Class="WPF_Question_Answer_App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_Question_Answer_App"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:MouseMoveCommandUserControl MouseMoveCommand="{Binding SomeMouseMoveCommand}"
MouseMoveCommandParameter="{Binding SomeMouseMoveCommandParameter}"/>
</Grid>
</Window>
希望这有助于。。。如果没有,我将删除答案,请告诉我。这只是一个如何使用内置组件实现的示例 您可以利用已经存在的UI组件来实现大部分目标。有副作用(不能连续两次单击同一个平铺,需要修改选择行为等),但这是另一种方式 在窗口中,使用带有适当面板的列表框。在我的示例中,您可以将此作为tic-tac-toe游戏的基础:
<Window x:Class="TileClicker.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:TileClicker"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<ListBox
ItemsSource="{Binding Tiles}"
SelectedItem="{Binding SelectedTile}" DisplayMemberPath="Name">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid
Rows="3"
Columns="3" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Window>
我们的瓷砖由
public class Tile : Notifier
{
private string _name = "Click me";
public string Name
{
get
{
return _name;
}
set { _name = value; Notify(); }
}
}
我们的视图模型使用SelectedItem绑定来知道何时单击了一个平铺,并做出相应的响应
public class ViewModel : Notifier
{
private Tile _tile;
public ObservableCollection<Tile> Tiles { get; } = new ObservableCollection<Tile> {
new Tile(), new Tile(), new Tile(),
new Tile(), new Tile(), new Tile(),
new Tile(), new Tile(), new Tile()
};
public Tile SelectedTile
{
get
{
return _tile;
}
set
{
_tile = value;
Notify();
UpdateName(value);
}
}
private void UpdateName(Tile value)
{
if(value.Name == "Click me")
value.Name = "Woot!";
else
value.Name = "Click me";
}
}
这只是一个如何使用内置组件实现的示例 您可以利用已经存在的UI组件来实现大部分目标。有副作用(不能连续两次单击同一个平铺,需要修改选择行为等),但这是另一种方式 在窗口中,使用带有适当面板的列表框。在我的示例中,您可以将此作为tic-tac-toe游戏的基础:
<Window x:Class="TileClicker.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:TileClicker"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<ListBox
ItemsSource="{Binding Tiles}"
SelectedItem="{Binding SelectedTile}" DisplayMemberPath="Name">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid
Rows="3"
Columns="3" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Window>
我们的瓷砖由
public class Tile : Notifier
{
private string _name = "Click me";
public string Name
{
get
{
return _name;
}
set { _name = value; Notify(); }
}
}
我们的视图模型使用SelectedItem绑定来知道何时单击了一个平铺,并做出相应的响应
public class ViewModel : Notifier
{
private Tile _tile;
public ObservableCollection<Tile> Tiles { get; } = new ObservableCollection<Tile> {
new Tile(), new Tile(), new Tile(),
new Tile(), new Tile(), new Tile(),
new Tile(), new Tile(), new Tile()
};
public Tile SelectedTile
{
get
{
return _tile;
}
set
{
_tile = value;
Notify();
UpdateName(value);
}
}
private void UpdateName(Tile value)
{
if(value.Name == "Click me")
value.Name = "Woot!";
else
value.Name = "Click me";
}
}
感谢您提供代码。我必须编写一个应用程序来用Tiles(
GameFieldTileViewModel
)构建地图。初始地图将填充草地地砖
。另外,我还有一个包装袋,里面装满了可能要放置的瓷砖(PlaseableObject
)。单击其中一个PlaseableObject
后,我生成一个新的GameFieldTileViewModel
并将其添加到我的GameFieldContent
集合中。现在我想将其X/Y坐标更改为我用鼠标输入的GrassfieldTiles
的X/Y坐标,因此,我希望有一个MouseEnterCommand
,将输入的Tile作为参数。如果要添加到WrapPanel中的控件是PlaseableObject或GrassfieldTiles,并且希望在这些控件上有一个MouseMoveCommand,那么只需将我上面给出的DependencyProperties复制并粘贴到这些控件中即可。然后在构造函数中添加MouseMove事件以尝试触发该命令,并最终将该命令绑定到控件,就像绑定任何其他普通命令一样。当鼠标在控件中移动时,命令将启动(或测试启动)。是的,但是如何将GameFieldTileViewModel
绑定到MouseMoveCommandParameter
?当我像在MouseBinding
中那样做时,我在if(MouseMoveCommand.CanExecute(MouseMoveCommand参数))
中得到NullReferenceException
!现在我有了!我忘了什么!非常感谢。你保护了我的一天!=)又来了!我成功地复制了您的mouseweel
代码,我需要如何自定义该代码以通过命令获得mouseweel
的方向?感谢您提供代码。我必须编写一个应用程序来用Tiles(GameFieldTileViewModel
)构建地图。初始地图将填充草地地砖
。另外,我还有一个包装袋,里面装满了可能要放置的瓷砖(PlaseableObject
)。单击其中一个PlaseableObject
后,我生成一个新的GameFieldTileViewModel
并将其添加到我的GameFieldContent
集合中。现在我想将其X/Y坐标更改为我用鼠标输入的GrassfieldTiles
的X/Y坐标,因此,我希望有一个MouseEnterCommand
,将输入的Tile作为参数。如果要添加到WrapPanel中的控件是PlaseableObject或GrassfieldTiles,并且希望在这些控件上有一个MouseMoveCommand,那么只需将我上面给出的DependencyProperties复制并粘贴到这些控件中即可。然后在构造函数中添加MouseMove事件以尝试触发该命令,并最终将该命令绑定到控件,就像绑定任何其他普通命令一样。当鼠标在控件中移动时,命令将启动(或测试启动)。是的,但是如何将GameFieldTileViewModel
绑定到MouseMoveCommandParameter
?当我像在MouseBinding
I中那样做时