Как получить объект из ItemsControl по нажатию на него WPF
У меня есть поле для рисования, вот его код на xaml:
<Grid Grid.Column="1">
<Rectangle Fill="Beige" MouseLeftButtonDown="Rectangle_MouseLeftButtonDown"/>
<ItemsControl ItemsSource="{Binding Vertices}">
<ItemsControl.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding ClickOnVertex}"/>
</ItemsControl.InputBindings>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding X}"/>
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate >
<Ellipse Width="20" Height="20" Fill="Black"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Это поле по шаблону отображает объекты VisualVertex из наблюдаемой коллекции Vertices.
Что мне передать в CommandParameter, чтоб в методе ClickOnVertex я получит объект, на который нажал
Код класса VisualVertex:
public class VisualVertex: INotifyPropertyChanged
{
#region fields
/// <summary>
/// Вершина.
/// </summary>
private Vertex _vertex;
/// <summary>
/// Цвет.
/// </summary>
private Brush _color;
#endregion
#region properties
/// <summary>
/// Вершина.
/// </summary>
public Vertex Vertex
{
get
{
return _vertex;
}
private set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value), "Пустая вершина.");
}
_vertex = value;
}
}
/// <summary>
/// Ширина.
/// </summary>
public int Width { get; set; }
/// <summary>
/// Высота.
/// </summary>
public int Height { get; set; }
/// <summary>
/// Коориднаты.
/// </summary>
public (double, double) Coordinates
{
get
{
return _vertex.Сoordinates;
}
set
{
_vertex.Сoordinates = value;
OnPropertyChanged(nameof(Coordinates));
}
}
public double X
{
get
{
return _vertex.Сoordinates.Item1;
}
}
public double Y
{
get
{
return _vertex.Сoordinates.Item2;
}
}
/// <summary>
/// Номер.
/// </summary>
public int Number
{
get
{
return _vertex.Number;
}
set
{
_vertex.Number = value;
OnPropertyChanged(nameof(Number));
}
}
/// <summary>
/// Название.
/// </summary>
public string Name
{
get
{
return _vertex.Name;
}
set
{
_vertex.Name = value;
OnPropertyChanged(nameof(Name));
}
}
/// <summary>
/// Цвет.
/// </summary>
public Brush Color
{
get
{
return _color;
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value), "Пустой цвет.");
}
_color = value;
OnPropertyChanged(nameof(Color));
}
}
public event PropertyChangedEventHandler? PropertyChanged;
#endregion
#region constructors
/// <summary>
/// Конструктор.
/// </summary>
/// <param name="x">X координата.</param>
/// <param name="y">Y координата.</param>
/// <param name="number">Номер вершины.</param>
/// <param name="color">Цвет.</param>
/// <param name="name">Название.</param>
public VisualVertex(double x, double y, int number, Color color, string name = "default")
{
_vertex = new Vertex(x, y , number, name);
Color = new SolidColorBrush(color);
}
/// <summary>
/// Конструктор.
/// </summary>
/// <param name="coordinates">Координаты.</param>
/// <param name="number">Номер вершины.</param>
/// <param name="color">Цвет.</param>
/// <param name="name">Название.</param>
public VisualVertex((double, double) coordinates, int number, Color color, string name = "default")
{
_vertex = new Vertex(coordinates, number, name);
Color = new SolidColorBrush(color);
}
#endregion
#region private methods
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Код ViewModel
public class MainWindowViewModel
{
#region fields
/// <summary>
/// Команда изменения режима мыши.
/// </summary>
private RelayCommand _changeMouseMode;
/// <summary>
/// Команда добавыления вершины.
/// </summary>
private RelayCommand _clickOnField;
/// <summary>
/// Команда нажатия на вершину.
/// </summary>
private RelayCommand _clickOnVertex;
/// <summary>
/// Режим мыши.
/// </summary>
private static MouseMode _mouseMode;
#endregion
#region properties
/// <summary>
/// Свойство команды изменения режима мыши.
/// </summary>
public RelayCommand ChangeMouseMode
{
get
{
return _changeMouseMode;
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value), "Команда является пустой.");
}
_changeMouseMode = value;
}
}
/// <summary>
/// Команда добавления вершины.
/// </summary>
public RelayCommand ClickOnField
{
get
{
return _clickOnField;
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value), "Пустая команда нажатия на поле.");
}
_clickOnField = value;
}
}
/// <summary>
/// Команда нажатия на вершину.
/// </summary>
public RelayCommand ClickOnVertex
{
get
{
return _clickOnVertex;
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value), "Пустая команда нажатия на вершину.");
}
_clickOnVertex = value;
}
}
public VisualVertex SelectedVertex { get; set; }
/// <summary>
/// Лист вершин.
/// </summary>
public ObservableCollection<VisualVertex> Vertices { get; set; }
#endregion
#region constructor
/// <summary>
/// Конструктор.
/// </summary>
public MainWindowViewModel()
{
Vertices = new ObservableCollection<VisualVertex>();
ChangeMouseMode = new RelayCommand(SetMouseMode);
ClickOnField = new RelayCommand(ClickOnFieldCommand);
ClickOnVertex = new RelayCommand(ClickOnVertexCommand);
}
#endregion
#region public methods
#endregion
#region private methods
/// <summary>
/// Изменение режима мыши.
/// </summary>
/// <param name="mode">Режим мыши.</param>
private void SetMouseMode(object mode)
{
_mouseMode = (MouseMode)mode;
}
/// <summary>
/// Команда нажатия на поле.
/// </summary>
/// <param name="parameter">Параметр.</param>
private void ClickOnFieldCommand(object parameter)
{
if (_mouseMode == MouseMode.Create)
{
AddVertexCommand((Point)parameter);
}
}
private void ClickOnVertexCommand(object parameter)
{
}
/// <summary>
/// Добавление новой вершины.
/// </summary>
/// <param name="parameter">Координаты верпшины.</param>
private void AddVertexCommand(Point point)
{
Vertices.Add(new VisualVertex(
(point.X, point.Y),
Vertices.Count + 1,
Colors.Black
));
}
#endregion
}
Ответы (1 шт):
Автор решения: zarnii
→ Ссылка
Не знаю на сколько это правильно, но я решил свою проблему с помощью Interaction.Triggers
Через NuGet добавил пакет Microsoft.Xaml.Behaviors.Wpf
В DataTemplate поменял код на следующий
<Ellipse Width="20" Height="20" Fill="Black">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseDown">
<i:InvokeCommandAction Command="{Binding Path=DataContext.ClickOnVertex, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Ellipse>
И теперь в метод параметром прилетает тот VisualVertex, на который я нажал.