Как привязать команду к событию ItemSelectionChanged в ListView? - PullRequest
0 голосов
/ 25 мая 2011

Возможно ли связать команду с ListView's ItemSelectionChanged ? Как? Если это невозможно, есть ли другой способ вызвать команду при изменении выбора в представлении списка?

Ответы [ 2 ]

1 голос
/ 25 мая 2011

Да - инфраструктура MVVM-light поддерживает привязку команд к маршрутизируемым событиям. Смотри http://blog.galasoft.ch/archive/2009/11/05/mvvm-light-toolkit-v3-alpha-2-eventtocommand-behavior.aspx

<Rectangle Fill="White"
           Stroke="Black"
           Width="200"
           Height="100">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter">
            <cmd:EventToCommand Command="{Binding TestCommand,
                                          Mode=OneWay}"
               CommandParameter="{Binding Text,
                                  ElementName=MyTextBox,
                                  Mode=OneWay}"
               MustToggleIsEnabledValue="True" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Rectangle>
0 голосов
/ 25 мая 2011

сначала я использую в своем проекте команду, в которой selectedItems передается в качестве параметра. Недостатком этого подхода является то, что пользователь должен нажать командную кнопку, чтобы начать действие, но в большинстве случаев это отвечает моим требованиям.

На пути к достижению того, что вы хотите, есть что-то наподобие erash - использовать такое поведение EventToCommand, как у mvvm-light.

другой способ - создать привязанное поведение для привязки к выбранным элементам в вашей модели представления. Вы должны перенести следующий код в ListView или создать что-то более общее:)

<DataGrid AttachedProperties:DatagridService.SelectedItemsSource="{Binding SelectedItems, Mode=OneWay}" />

ViewModel:

public ObservableCollection<object> SelectedItems//init collection just ONCE!
    {
        get
        {
            if (this.selectedItems == null)
            {
                this.selectedItems = new ObservableCollection<object>();
                this.selectedItems.CollectionChanged +=
                    new System.Collections.Specialized.NotifyCollectionChangedEventHandler(SelectedItemsCollectionChanged);
            }
            return this.selectedItems;
        }

    }

    private void SelectedItemsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        //this is called when ever the selecteditems changed
    }

Прикрепленное поведение:

public static class DatagridService
{
    #region SelectedItemSource

    #region Attached Property Declaration

    /// <summary>
    /// Identifies the ListBoxExtension.SelectedItemsSource attached property.
    /// </summary>
    public static readonly DependencyProperty SelectedItemsSourceProperty =
       DependencyProperty.RegisterAttached(
          "SelectedItemsSource",
          typeof(IList),
          typeof(DatagridService),
          new PropertyMetadata(
              null,
              new PropertyChangedCallback(OnSelectedItemsSourceChanged)));

    #endregion

    #region Attached Property Accessors

    /// <summary>
    /// Gets the IList that contains the values that should be selected.
    /// </summary>
    /// <param name="element">The ListBox to check.</param>
    public static IList GetSelectedItemsSource(DependencyObject element)
    {
        if (element == null)
            throw new ArgumentNullException("element");

        return (IList)element.GetValue(SelectedItemsSourceProperty);
    }

    /// <summary>
    /// Sets the IList that contains the values that should be selected.
    /// </summary>
    /// <param name="element">The ListBox being set.</param>
    /// <param name="value">The value of the property.</param>
    public static void SetSelectedItemsSource(DependencyObject element, IList value)
    {
        if (element == null)
            throw new ArgumentNullException("element");

        element.SetValue(SelectedItemsSourceProperty, value);
    }

    #endregion

    #region IsResynchingProperty

    // Used to set a flag on the ListBox to avoid reentry of SelectionChanged due to
    // a full syncronisation pass
    private static readonly DependencyPropertyKey IsResynchingPropertyKey =
       DependencyProperty.RegisterAttachedReadOnly(
            "IsResynching",
            typeof(bool),
            typeof(DatagridService),
            new PropertyMetadata(false));

    #endregion

    #region Private Static Methods

    private static void OnSelectedItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        DataGrid grd = d as DataGrid;
        if (grd == null)
            throw new InvalidOperationException("The DataGridExtension.SelectedItemsSource attached " +
               "property can only be applied to DataGrid controls.");

        grd.SelectionChanged -= new SelectionChangedEventHandler(OnDataGridSelectionChanged);

        if (e.NewValue != null)
        {
            ListenForChanges(grd);
        }

        BindingExpression bexp = grd.GetBindingExpression(SelectedItemsSourceProperty);
        if (bexp != null)
            bexp.UpdateSource();

    }

    private static void ListenForChanges(DataGrid grd)
    {
        // Wait until the element is initialised
        if (!grd.IsInitialized)
        {
            EventHandler callback = null;
            callback = delegate
            {
                grd.Initialized -= callback;
                ListenForChanges(grd);
            };
            grd.Initialized += callback;
            return;
        }

        grd.SelectionChanged += new SelectionChangedEventHandler(OnDataGridSelectionChanged);
        ResynchList(grd);
    }

    private static void OnDataGridSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        DataGrid grd = sender as DataGrid;
        if (grd != null)
        {
            bool isResynching = (bool)grd.GetValue(IsResynchingPropertyKey.DependencyProperty);
            if (isResynching)
                return;

            IList list = GetSelectedItemsSource(grd);

            if (list != null)
            {
                foreach (object obj in e.RemovedItems)
                {
                    if (list.Contains(obj))
                        list.Remove(obj);
                }
                foreach (object obj in e.AddedItems)
                {

                    if (!list.Contains(obj))
                        list.Add(obj);
                }
            }
        }
    }

    private static void ResynchList(DataGrid grd)
    {
        if (grd != null)
        {
            grd.SetValue(IsResynchingPropertyKey, true);
            IList list = GetSelectedItemsSource(grd);

            if (grd.SelectionMode == DataGridSelectionMode.Single)
            {
                grd.SelectedItem = null;
                if (list != null)
                {
                    if (list.Count > 1)
                    {
                        // There is more than one item selected, but the listbox is in Single selection mode
                        throw new InvalidOperationException("DataGrid is in Single selection mode, but was given more than one selected value.");
                    }

                    if (list.Count == 1)
                        grd.SelectedItem = list[0];
                }
            }
            else
            {
                grd.SelectedItems.Clear();
                if (list != null)
                {
                    foreach (object obj in grd.Items)
                        if (list.Contains(obj))
                            grd.SelectedItems.Add(obj);
                }
            }

            grd.SetValue(IsResynchingPropertyKey, false);
        }
    }

    #endregion

    #endregion
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...