Нельзя использовать событие на клик из контекстного меню listbox
Возникает ошибка:
InvalidCastException: Не удалось привести тип объекта "System.Windows.Controls.MenuItem" к типу "System.Windows.Controls.Button".
using MySql.Data.MySqlClient;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Input;
namespace Wpcon
{
public partial class Window1 : Window
{
public ObservableCollection<list_cams> list_camsl = new ObservableCollection<list_cams>();
public class list_cams
{
public string Nomercam { get; set; }
public string Adrescam { get; set; }
}
public Window1()
{
InitializeComponent();
list_camsl.Add(new list_cams { Nomercam ="12323", Adrescam = "asdasd" });
list_cam.ItemsSource = list_camsl;
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("ZZzzz");
}
}
}
XAML
<ListBox x:Name="list_cam" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Stretch" MinHeight="150px" Margin="0,0,5,0" VerticalAlignment="Stretch" ItemsSource="{Binding cam_list}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="3">
<DockPanel>
<TextBlock FontWeight="Bold" Text="Номер:" Foreground="Black" DockPanel.Dock="Left" Margin="5,0,5,0" />
<TextBlock Text="{Binding Nomercam}" />
</DockPanel>
<DockPanel>
<TextBlock FontWeight="Bold" Text="Адрес:" Foreground="DarkOrange" DockPanel.Dock="Left" Margin="5,0,5,0" />
<TextBlock Text="{Binding Adrescam}" />
</DockPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Редактировать"/>
<MenuItem Header="Удалить" Click="MenuItem_Click" />
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Ответы (1 шт):
Автор решения: aepot
→ Ссылка
Там не все так просто с этим меню оказалось. Созданное внутри ItemContainerStyle оно оказалось не живое, ни для обработчиков событий, не для команд. Поэтому создал я его в ресурсах ListBox.
Я написал реализацию с командами. Для использования команд, вам нужно добавить в проект класс, отдельным файлом. В проводнике решения выберите Добавить - Класс - RelayCommand.cs.
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);
public void Execute(object parameter) => _execute(parameter);
}
Вникать в его логику не обязательно на данном этапе. А использовать его достаточно просто.
Вот код окна
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<Cam> _cams;
private ICommand _editCommand;
private ICommand _deleteCommand;
public ObservableCollection<Cam> Cams
{
get => _cams;
set
{
_cams = value;
OnPropertyChanged(); // эта штука позволяет сохранять связь с коллекцией если вы ее переприсвоите во время работы приложения
}
}
public ICommand EditCommand => _editCommand ?? (_editCommand = new RelayCommand(parameter =>
{
if (parameter is Cam cam)
{
MessageBox.Show(cam.Nomercam + " " + cam.Adrescam, "Редактировать");
}
}));
public ICommand DeleteCommand => _deleteCommand ?? (_deleteCommand = new RelayCommand(parameter =>
{
if (parameter is Cam cam)
{
MessageBox.Show(cam.Nomercam + " " + cam.Adrescam, "Удалить");
Cams.Remove(cam);
}
}));
public MainWindow()
{
InitializeComponent();
DataContext = this;
// Не пишите в конструктор свой код, пишите его в обработчик Window.Loaded
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Cams = new ObservableCollection<Cam>();
Cams.Add(new Cam { Nomercam = "12323", Adrescam = "asdasd" });
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Класс данных отдельно
public class Cam : INotifyPropertyChanged
{
private string _nomercam;
private string _adrescam;
public string Nomercam
{
get => _nomercam;
set
{
_nomercam = value;
OnPropertyChanged();
}
}
public string Adrescam
{
get => _adrescam;
set
{
_adrescam = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Разметка
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Width="1200" Height="600" Loaded="Window_Loaded">
<Grid>
<ListBox Margin="5" ItemsSource="{Binding Cams}">
<ListBox.Resources>
<ContextMenu x:Key="MyContextMenu">
<MenuItem Header="Редактировать" Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}"/>
<MenuItem Header="Удалить" Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="{Binding}"/>
</ContextMenu>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="3">
<DockPanel>
<TextBlock FontWeight="Bold" Text="Номер:" Foreground="Black" DockPanel.Dock="Left" Margin="5,0,5,0" />
<TextBlock Text="{Binding Nomercam}" />
</DockPanel>
<DockPanel>
<TextBlock FontWeight="Bold" Text="Адрес:" Foreground="DarkOrange" DockPanel.Dock="Left" Margin="5,0,5,0" />
<TextBlock Text="{Binding Adrescam}" />
</DockPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="ContextMenu" Value="{StaticResource MyContextMenu}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid>
</Window>
Так же я немного переименовал ваши классы и переменные - ссылка.