powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Присоединяемое событие ListBoxItem.Selected
15 сообщений из 15, страница 1 из 1
Присоединяемое событие ListBoxItem.Selected
    #39714833
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кто может объяснить почему для кнопок работает присоединяемое событие Button.Click, а для ListBoxItem.Selected - нет?
Пример XAML окна
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
        <StackPanel Button.Click="Button_Click">
            <Button Content="Кнопка 1"/>
            <Button Content="Кнопка 2"/>
            <Button Content="Кнопка 3"/>
            <ListBox ListBoxItem.Selected="ListBoxItem_Selected">
                <ListBoxItem Content="Строка 1"/>
                <ListBoxItem Content="Строка 2"/>
                <ListBoxItem Content="Строка 3"/>
            </ListBox>
            <TextBlock x:Name="myTB" />
        </StackPanel>

Обработчики в коде окна
Код: c#
1.
2.
3.
4.
5.
        private void Button_Click(object sender, RoutedEventArgs e) 
            => myTB.Text = "Событие Button.Click "+((Button)e.OriginalSource).Content;
 
        private void ListBoxItem_Selected(object sender, RoutedEventArgs e) 
            => myTB.Text = "Событие ListBoxItem_Selected " + ((ListBoxItem)e.OriginalSource).Content;
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39714976
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Eld Haspприсоединяемое событиеЧто за новый зверь? Есть маршрутизируемое событие


Событие Selected есть у Selector, а ListBoxItem не является селектором
Код: xml
1.
<ListBox Selected="ListBox_Selected">
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39715028
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Shocker.Pro, но есть же событие ListBoxItem.Selected. И если записать, так
Код: xml
1.
2.
3.
4.
5.
            <ListBox>
                <ListBoxItem Content="Строка 1" Selected="ListBoxItem_Selected"/>
                <ListBoxItem Content="Строка 2" Selected="ListBoxItem_Selected"/>
                <ListBoxItem Content="Строка 3" Selected="ListBoxItem_Selected"/>
            </ListBox>

То работает. По документации эта запись равносильно предыдущей, так же как и для кнопок. В редакторе при вводе XAML кода ListBox выходит подсказка с этим присоединённым свойством. Но оно не работает. Ошибок тоже не выдаёт.
Я вот и понять не могу в чём дело?
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39715038
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Shocker.ProСобытие Selected есть у Selector, а ListBoxItem не является селектором
Код: xml
1.
<ListBox Selected="ListBox_Selected">

При такой записи при сборке проекта выдаёт ошибку " CS1061 C# "ListBox" не содержит определения для "Selected", и не удалось найти доступный метод расширения "Selected", принимающий тип "ListBox" в качестве первого аргумента (возможно, пропущена директива using или ссылка на сборку). "
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39715054
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProЧто за новый зверь?
Не, не новый: Attached Events Overview
Вот это:
Код: xml
1.
<StackPanel Button.Click="Button_Click">


неявно добавляет в скомпилированный код вот такую штуку:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
[DebuggerNonUserCode]
[EditorBrowsable(EditorBrowsableState.Never)]
[GeneratedCode("PresentationBuildTasks", "4.0.0.0")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target)
{
  if (connectionId == 1)
  {
    ((StackPanel)target).AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(this.Button_Click));
  }
  else
  {
    this._contentLoaded = true;
  }
}


ну, а для ListBoxItem это не работает потому, что листбокс в своем статическом конструкторе для себя переопределяет ряд событий, в т.ч. MouseUp, которое ответственно в т.ч. за формирование события Click у кнопки.
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39715076
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сон Веры Павловныну, а для ListBoxItem это не работает потому, что листбокс в своем статическом конструкторе для себя переопределяет ряд событий, в т.ч. MouseUp, которое ответственно в т.ч. за формирование события Click у кнопки.Зачем тогда оставили это в синтаксисе ListBox, в подсказках к нему? Только в заблуждения вводят.

А что с событием ListBox.Selected? Почему оно в редакторе, в подсказках есть, а при сборке выдаёт ошибку?
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39715325
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Eld HaspСон Веры Павловныну, а для ListBoxItem это не работает потому, что листбокс в своем статическом конструкторе для себя переопределяет ряд событий, в т.ч. MouseUp, которое ответственно в т.ч. за формирование события Click у кнопки.
А что с событием ListBox.Selected? Почему оно в редакторе, в подсказках есть, а при сборке выдаёт ошибку?
А, я думал, впрос про почему Button.Click на ListBoxItem не отрабатывает.
Приаттаченный к листбоксу ListBoxItem.Selected не отрабатывает при выборе ListBoxItem по той причине, что ListBoxItem унаследован от Visual, и генерируемые им routed events (которым в т.ч. является событие Selected) распространяются по визуальному дереву. А элементы, сгенерированные в ItemsControl (от которого унаследован ListBox), не являются частью визуального дерева самого ItemsControl, т.е. ListBoxItem, и ListBox - это разные визуальные дереья, поэтому событие просто не может всплыть до ListBox.
Иллюстрация:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
<Grid>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <ListBox ListBoxItem.Selected="Selector_OnSelected">
    <ListBoxItem Content="Строка 1"/>
    <ListBoxItem Content="Строка 2"/>
    <ListBoxItem Content="Строка 3"/>
  </ListBox>
  <StackPanel Grid.Row="1" ListBoxItem.Selected="StackPanel_OnSelected">
    <ListBoxItem
      x:Name="InsideStackPanel"
      Content="Inside StackPanel"
      Selected="ListBoxItem_OnSelected"/>
  </StackPanel>
  <Button
    Grid.Row="2"
    Content="test"
    VerticalAlignment="Center"
    HorizontalAlignment="Center"
    Click="Button_Click" />
</Grid>


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
public partial class MainWindow
{
  public MainWindow()
  {
    InitializeComponent();
  }

  void Button_Click(object sender, RoutedEventArgs e)
  {
    InsideStackPanel.IsSelected = true;
  }

  void Selector_OnSelected(object sender, RoutedEventArgs e)
  {
    MessageBox.Show("StackPanel.ListBoxItem.Selected");
  }

  void StackPanel_OnSelected(object sender, RoutedEventArgs e)
  {
    MessageBox.Show("StackPanel.ListBoxItem.Selected");
  }

  void ListBoxItem_OnSelected(object sender, RoutedEventArgs e)
  {
    MessageBox.Show("ListBoxItem.Selected");
  }
}


- пли клике на нижнюю кнопку у ListBoxItem внутри StackPanel свойство IsSelected становится равно true, после чего вполне нормально отрабатывает ListBoxItem_OnSelected, и после него StackPanel_OnSelected, т.к. в этом случае ListBoxItem вполне находится внутри визуального дерева StackPanel.
В общем, читайте общие сведения про routed events и деревья .
Eld HaspЗачем тогда оставили это в синтаксисе ListBox, в подсказках к нему? Только в заблуждения вводят.
Потому что механизм attached events является общим для всех элементов, унаследованных от UIElement, он определен внутри UIElement, и понятия не имеет о нюансах в своих многочисленных наследниках.
P.S. Опять налицо какие-то странные манипуляции с тем, что в WPF делается легко и просто стандартными методами (в данном случае биндингом свойств). Мне за 8 лет работы с WPF ни разу не понабились attached events. Команды, присоединяемые к событиям через ACB и EventTrigger'ы, мне понадобились раза три от силы, и в очень экзотических случаях.
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39715491
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
есть логическое дерево и визуальное, учитывайте этот момент.
правильнее писать не Button.Click, а ButtonBase.Click

не могу понять, чего автор пытается добиться :)
может имеет смысл использовать команды и CommandBinding?
сами RoutedEvent'ы для внутренней реализации контролов, а не прикладного функционала.
У селектора существует свойство SelectionChanged, использовать нужно его, а не городить какую то фигню, но лично я даже так не делаю, потому что вопрос выделения и списка выделенных элементов обычно лежит на представлении списка и требуется только в VM
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39715791
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Roman Mejtesне могу понять, чего автор пытается добиться :)Пытаюсь обучиться. При чтении натыкаюсь на что-то повторяю, пытаюсь изменить. Всплывает непонятное. И "добиваюсь" понимая - но порой не доходит сразу.
Roman Mejtesно лично я даже так не делаю, потому что вопрос выделения и списка выделенных элементов обычно лежит на представлении списка и требуется только в VM А если это нужно только для взаимодействия элементов внутри окна. Изменения в данных это не влечёт за собой. По выбранному значению в одном элементе надо "подсветить" значения в другом. Как тогда лучше сделать? Нужно ли для этого привлекать VM? Что посоветуете?
Сон Веры ПавловныВ общем, читайте общие сведения про routed events и деревья.Читал, но похоже плохо. Буду дальше штудировать. Просто мне в голову даже не пришёл вариант, что вложенный элемент может быть из другого дерева. Спасибо за внимание.
Сон Веры ПавловныОпять налицо какие-то странные манипуляции с тем, что в WPF делается легко и просто стандартными методами (в данном случае биндингом свойств)Это скорее от незнания. Читаю - но знания появляются значительно медленнее чем накапливается информация из прочитанного. Поэтому в голове от дальнейшего чтения - бардак. Пытаюсь как-то применить прочитанное чтобы разобраться в этом бардаке.
Что касается данного примера, то событие Selected лучше обработать в привязке свойства SelectedItem родительского ListBox. Я правильно Вас понял?
Сон Веры ПавловныКоманды, присоединяемые к событиям через ACB и EventTrigger'ы, мне понадобились раза три от силы, и в очень экзотических случаях.Roman Mejtesможет имеет смысл использовать команды и CommandBinding?А тогда такой вопрос. Два ListBox. При наведении курсора в первом (событие MouseEnter) надо изменять доступный список значений во втором ListBox. У меня это сделано опять таки через EventSetter в стиле для вложенных ListBoxItem. А как правильно такое сделать? Без использования EventSetter?
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39715899
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Eld HaspА тогда такой вопрос. Два ListBox. При наведении курсора в первом (событие MouseEnter) надо изменять доступный список значений во втором ListBox. У меня это сделано опять таки через EventSetter в стиле для вложенных ListBoxItem. А как правильно такое сделать? Без использования EventSetter?
Зачем здесь MouseEnter? Чтобы все дергалось при каждом чихе мыши?
Я так понимаю, что требуются два зависимых списка, и набор значений второго зависит от выбранного значения в первом - обычное отношение master-detail. Это все можно сделать через один биндинг к выбранному значению в первом списке, отображающем элементы, сами содержащие список:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
public partial class MainWindow
{
  public MainWindow()
  {
    InitializeComponent();
    DataContext = new TypesModel();
  }
}

public class TypesModel : INotifyPropertyChanged
{
  public TypesModel()
  {
    MemberTypes = ClassMembers.GetMembers(typeof(Window)).ToList();
    SelectedMemberType = MemberTypes.First();
  }

  public IReadOnlyCollection<ClassMembers> MemberTypes { get; }

  ClassMembers _selectedMemberType;
  public ClassMembers SelectedMemberType
  {
    get => _selectedMemberType;
    set
    {
      _selectedMemberType = value;
      OnPropertyChanged();
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}

public enum MemberType
{
  [Description("Конструктор")]
  Constructor,
  [Description("Метод")]
  Method,
  [Description("Свойство")]
  Property,
  [Description("Поле")]
  Field,
  [Description("Событие")]
  Event
}

public class ClassMembers
{
  public Type Type { get; }
  public MemberType MemberType { get; }
  public ClassMembers(Type type, MemberType memberType)
  {
    Type = type;
    MemberType = memberType;
    DisplayName = (Attribute.GetCustomAttribute(typeof(MemberType).GetField(memberType.ToString())
      , typeof(DescriptionAttribute)) as DescriptionAttribute)?.Description;
    Func<IEnumerable<MemberInfo>> members;
    switch(MemberType)
    {
      case MemberType.Constructor:
        members = Type.GetConstructors;
        break;
      case MemberType.Method:
        members = Type.GetMethods;
        break;
      case MemberType.Property:
        members = Type.GetProperties;
        break;
      case MemberType.Event:
        members = Type.GetEvents;
        break;
      case MemberType.Field:
        members = ()=>Type.GetFields(BindingFlags.Static | BindingFlags.Public);
        break;
      default:
        throw new ArgumentException($"Unsupported MemberType value ({MemberType})");
    }
    Members = members().Select(mi => mi.Name).OrderBy(s => s).ToList();
  }

  public string DisplayName { get; }

  public IReadOnlyCollection<string> Members { get; }

  public override bool Equals(object obj)=>
    obj is ClassMembers cm && cm.Type==Type && cm.MemberType==MemberType;

  public override int GetHashCode() =>
    ((Func<int[], int>) (hashes =>
        hashes.Aggregate(hashes.Length, (current, t) => unchecked(current * 314159 + t))))
      (new[] {Type.GetHashCode(), MemberType.GetHashCode()});

  public static IEnumerable<ClassMembers> GetMembers(Type type) =>
    from MemberType mt in Enum.GetValues(typeof(MemberType)) select new ClassMembers(type, mt);
}


Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
<Grid>
  <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition />
  </Grid.ColumnDefinitions>
  <ListBox
    Margin="5"
    ItemsSource="{Binding MemberTypes}"
    SelectedItem="{Binding SelectedMemberType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
    DisplayMemberPath="DisplayName" />
  <ListBox
    Grid.Column="1"
    Margin="5"
    ItemsSource="{Binding SelectedMemberType.Members}" />
</Grid>
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39716013
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сон Веры ПавловныЗачем здесь MouseEnter? Чтобы все дергалось при каждом чихе мыши?Спасибо за внимание!
Организовано так: при наведении мыши на элемент (MouseEnter) в первом ListBox - во втором отображается список элементов второго уровня в режиме подсказки. Пользователь просматривает его, если это нужный список - он выбирает этот список и, при выходе из первого ListBox, во втором отображается список соответствующий выбранному из первого (SelectedItem). Я поэтому и говорю, что обработка события MouseEnter по сути имеет только вспомогательную, визуальную функцию. На выбор данных это не влияет.
Как методологически верно будет разделить в этом случае функции между View и VM? Где и как правильнее производить вывод информации для второго ListBox в режиме подсказки? Что можно использовать вместо прямой обработке в коде события MouseEnter?
Первоначально, я делал даже, два отдельных ListBox (получалось всего три ListBox): один для отображения выбранного списка, второй для режима подсказки. Но так как по сути они отображают сходные данные и которые не нужны одновременно, решил совместить эти функции в одном ListBox.
Интересует, в первую очередь, сама методология разделения функций в рамках MVVM.
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39716028
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39716037
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Eld HaspГде и как правильнее производить вывод информации для второго ListBox в режиме подсказки?
Там, где обычно выводятся подсказки - в тултипе:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
<Grid>
  <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition />
  </Grid.ColumnDefinitions>
  <ListBox
    Margin="5"
    ItemsSource="{Binding MemberTypes}"
    SelectedItem="{Binding SelectedMemberType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
    DisplayMemberPath="DisplayName">
    <ListBox.ItemContainerStyle>
      <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="ToolTip">
          <Setter.Value>
            <ToolTip MaxHeight="200">
              <ItemsControl ItemsSource="{Binding Members}" />
            </ToolTip>
          </Setter.Value>
        </Setter>
      </Style>
    </ListBox.ItemContainerStyle>
  </ListBox>
  <ListBox
    Grid.Column="1"
    Margin="5"
    ItemsSource="{Binding SelectedMemberType.Members}" />
</Grid>
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39716122
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сон Веры ПавловныТам, где обычно выводятся подсказки - в тултипе:
Да, действительно так лучше смотрится. Спасибо!
vb_subпохожая темаСпасибо за совет!
Посмотрел, но там не много другое. Там обрабатывается выбор элементов. В моём случае больше подходит совет Сон Веры Павловны - использовать тултип.
...
Рейтинг: 0 / 0
Присоединяемое событие ListBoxItem.Selected
    #39716126
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сон Веры Павловны, есть ещё одно место где использую триггера - цвет выделения в ListBox.
Но мы, уже сильно отклонились от начальной темы, чтобы не было путаницы - начну новую.
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Присоединяемое событие ListBoxItem.Selected
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]