Nano Hash - криптовалюты, майнинг, программирование

Прикрепленное поведение для выполнения команды для ListViewItem

Я пытаюсь использовать прикрепленное поведение для выполнения команды в моей модели просмотра, когда пользователь дважды щелкает элемент списка.

Я просмотрел несколько статей на эту тему и попытался создать простое тестовое приложение, но у меня все еще возникают проблемы, например. Запуск события двойного щелчка из WPF Элемент ListView с использованием MVVM

Моя простая тестовая модель ViewModel имеет 2 коллекции, одна из которых возвращает список строк, а другая - список типов ListViewItem.

public class ViewModel
{
    public ViewModel()
    {
        Stuff = new ObservableCollection<ListViewItem>
                    {
                        new ListViewItem { Content = "item 1" },
                        new ListViewItem { Content = "item 2" }
                    };

        StringStuff = new ObservableCollection<string> { "item 1", "item 2" };
    }

    public ObservableCollection<ListViewItem> Stuff { get; set; }

    public ObservableCollection<string> StringStuff { get; set; }

    public ICommand Foo
    {
        get
        {
            return new DelegateCommand(this.DoSomeAction);
        }
    }

    private void DoSomeAction()
    {
        MessageBox.Show("Command Triggered");
    }
}

Вот прикрепленное свойство, которое похоже на другие примеры, которые вы видите:

public class ClickBehavior
{
    public static DependencyProperty DoubleClickCommandProperty = DependencyProperty.RegisterAttached("DoubleClick",
               typeof(ICommand),
               typeof(ClickBehavior),
               new FrameworkPropertyMetadata(null, new PropertyChangedCallback(ClickBehavior.DoubleClickChanged)));

    public static void SetDoubleClick(DependencyObject target, ICommand value)
    {
        target.SetValue(ClickBehavior.DoubleClickCommandProperty, value);
    }

    public static ICommand GetDoubleClick(DependencyObject target)
    {
        return (ICommand)target.GetValue(DoubleClickCommandProperty);
    }

    private static void DoubleClickChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
    {
        ListViewItem element = target as ListViewItem;
        if (element != null)
        {
            if ((e.NewValue != null) && (e.OldValue == null))
            {
                element.MouseDoubleClick += element_MouseDoubleClick;
            }
            else if ((e.NewValue == null) && (e.OldValue != null))
            {
                element.MouseDoubleClick -= element_MouseDoubleClick;
            }
        }
    }

    static void element_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        UIElement element = (UIElement)sender;
        ICommand command = (ICommand)element.GetValue(ClickBehavior.DoubleClickCommandProperty);
        command.Execute(null);
    }
}

В моем главном окне я определил стиль, который устанавливает прикрепленное поведение и привязывается к команде Foo.

<Window.Resources>
    <Style x:Key="listViewItemStyle" TargetType="{x:Type ListViewItem}">
        <Setter Property="local:ClickBehavior.DoubleClick" Value="{Binding Foo}"/>                 
    </Style>
</Window.Resources>

Прекрасно работает, когда определены ListViewItems:

<!-- Works -->
<Label Grid.Row="2" Content="DoubleClick click behaviour:"/>        
<ListView Grid.Row="2" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}">
    <ListViewItem Content="Item 3" />
    <ListViewItem Content="Item 4" />
</ListView>

Это тоже работает при привязке к списку типа ListViewItem:

<!-- Works when items bound are of type ListViewItem -->
<Label Grid.Row="3" Content="DoubleClick when bound to ListViewItem:"/>        
  <ListView Grid.Row="3" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}" ItemsSource="{Binding Stuff}">        
 </ListView>

Но это не так:

<!-- Does not work when items bound are not ListViewItem -->
<Label Grid.Row="4" Content="DoubleClick when bound to string list:"/>
  <ListView Grid.Row="4" Grid.Column="1" ItemContainerStyle="{StaticResource listViewItemStyle}" ItemsSource="{Binding StringStuff}">
</ListView>

В окне вывода вы видите ошибку, но вам трудно понять, что не так.
Ошибка System.Windows.Data: 39: Ошибка пути BindingExpression: свойство 'Foo' не найдено в 'объекте' '' Строка '(HashCode = 785742638)'. BindingExpression: Путь = Foo; DataItem = 'Строка' (HashCode = 785742638); целевой элемент - ListViewItem (Name = ''); целевое свойство - DoubleClick (тип ICommand)

Итак, мой вопрос: как вы можете правильно подключить команду к каждому ListViewItem, когда вы привязываете свой ListView к списку объектов модели?

Спасибо.

07.01.2011

  • Это было очень полезно! Для дополнительной возможности повторного использования я изменил ListViewItem element = target на ListViewItem; к элементу управления = цель как элемент управления; 05.12.2013

Ответы:


1

Проблема в том, что DataContext для Binding - это строка. Поскольку у строкового класса нет свойства Foo, вы получаете сообщение об ошибке. В других случаях этого не происходит, потому что они наследуют свои DataContext от родителя (этого не происходит для автоматически сгенерированных контейнеров для элементов данных - их DataContext является элементом данных).

Если вы измените привязку для использования родительского ListView DataContext, все должно работать нормально:

Value="{Binding DataContext.Foo, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}"
07.01.2011
  • Спасибо за быстрый ответ, Эйб. Вы звезда, слишком долго пытались понять это. 07.01.2011
  • Нет проблем, Пол. Ошибки привязки действительно загадочны, и иногда нужно просто взглянуть свежим взглядом, чтобы увидеть, что происходит! 07.01.2011
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..