1

Возникает ошибка:

 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 =&quot;12323&quot;, Adrescam = &quot;asdasd&quot; });
        list_cam.ItemsSource = list_camsl;
    }
    private void MenuItem_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(&quot;ZZzzz&quot;);
    }
}

}

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>
&lt;ListBox.ItemContainerStyle&gt;
    &lt;Style TargetType=&quot;ListBoxItem&quot;&gt;
        &lt;Setter Property=&quot;ContextMenu&quot;&gt;
            &lt;Setter.Value&gt;
                &lt;ContextMenu&gt;
                    &lt;MenuItem Header=&quot;Редактировать&quot;/&gt;
                    &lt;MenuItem Header=&quot;Удалить&quot; Click=&quot;MenuItem_Click&quot; /&gt;
                &lt;/ContextMenu&gt;
            &lt;/Setter.Value&gt;
        &lt;/Setter&gt;
    &lt;/Style&gt;
&lt;/ListBox.ItemContainerStyle&gt;

</ListBox>

aepot
  • 49,560
Tand
  • 163
  • Исправьте Button button = (Button)sender; на MenuItem menuItem = (MenuItem)sender; в обработчике события Samba. Вы скопировали обработчик из какой-то кнопки и забыли поменять тип. Внимательнее надо быть. – aepot Nov 29 '20 at 18:11
  • @aepot немного не понял это где нужно выставить, я такого не нахожу. Да и ничего не копировал – Tand Dec 01 '20 at 11:37
  • private void MenuItem_Click(object sender, RoutedEventArgs e) {
        }
    
    – Tand Dec 01 '20 at 11:37
  • #line 52 "....\Window1.xaml" this.Add_cams.AddHandler(System.Windows.Controls.MenuItem.ClickEvent, new System.Windows.RoutedEventHandler(this.MenuItem_Click)); – Tand Dec 01 '20 at 11:57
  • <MenuItem Header="Удалить" Click="Samba"/> - а это что тогда такое? У вас есть метод, который называется Samba – aepot Dec 01 '20 at 13:16
  • я его переименовал на MenuItem_Click – Tand Dec 02 '20 at 16:55
  • Я в xaml не вижу, что вы его переименовали. Покажите актуальный код, отредактируйте вопрос. И зачем вам назначать одновременно обработчик и в xaml и в коде, выберите что-то одно. И да, покажите C# код, без него можно только гадать, что у вас за ошибка. – aepot Dec 02 '20 at 17:42
  • @aepot обновил вопрос – Tand Dec 02 '20 at 17:56
  • Вот теперь в показанном коде я не вижу причин для указанной ошибки. Ошибка за пределами показанного кода. – aepot Dec 02 '20 at 18:16
  • @aepot в том то и дело что это весь код. – Tand Dec 03 '20 at 12:50
  • А где ошибка возникает, в какой строке? – aepot Dec 03 '20 at 12:54
  • @aepot в чате более подробно могу показать, дабы тут не писать лишние сообщения – Tand Dec 03 '20 at 12:59

1 Answers1

1

Там не все так просто с этим меню оказалось. Созданное внутри 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&lt;object&gt; execute, Func&lt;object, bool&gt; canExecute = null)
{
    _execute = execute;
    _canExecute = canExecute;
}

public bool CanExecute(object parameter) =&gt; _canExecute == null || _canExecute(parameter);
public void Execute(object parameter) =&gt; _execute(parameter);

}

Вникать в его логику не обязательно на данном этапе. А использовать его достаточно просто.

Вот код окна

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private ObservableCollection<Cam> _cams;
    private ICommand _editCommand;
    private ICommand _deleteCommand;
public ObservableCollection&lt;Cam&gt; Cams
{
    get =&gt; _cams;
    set
    {
        _cams = value;
        OnPropertyChanged(); // эта штука позволяет сохранять связь с коллекцией если вы ее переприсвоите во время работы приложения
    }
}

public ICommand EditCommand =&gt; _editCommand ?? (_editCommand = new RelayCommand(parameter =&gt;
{
    if (parameter is Cam cam)
    {
        MessageBox.Show(cam.Nomercam + &quot; &quot; + cam.Adrescam, &quot;Редактировать&quot;);
    }
}));

public ICommand DeleteCommand =&gt; _deleteCommand ?? (_deleteCommand = new RelayCommand(parameter =&gt;
{
    if (parameter is Cam cam)
    {
        MessageBox.Show(cam.Nomercam + &quot; &quot; + cam.Adrescam, &quot;Удалить&quot;);
        Cams.Remove(cam);
    }
}));

public MainWindow()
{
    InitializeComponent();
    DataContext = this;

    // Не пишите в конструктор свой код, пишите его в обработчик Window.Loaded
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    Cams = new ObservableCollection&lt;Cam&gt;();
    Cams.Add(new Cam { Nomercam = &quot;12323&quot;, Adrescam = &quot;asdasd&quot; });
}

public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    =&gt; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

}

Класс данных отдельно

public class Cam : INotifyPropertyChanged
{
    private string _nomercam;
    private string _adrescam;
public string Nomercam
{
    get =&gt; _nomercam;
    set
    {
        _nomercam = value;
        OnPropertyChanged();
    }
}
public string Adrescam
{
    get =&gt; _adrescam;
    set
    {
        _adrescam = value;
        OnPropertyChanged();
    }
}

public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    =&gt; 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>

Так же я немного переименовал ваши классы и переменные - ссылка.

aepot
  • 49,560