AttachedProperty против поведения, чтобы получить SelectedItems в ViewModel - PullRequest
0 голосов
/ 17 ноября 2018

У меня есть опции для получения SelectedItems в ViewModel.

Прикрепленное свойство, подобное этому:

public class ListBoxSelectedItemsAttachedProperty
    {
        #region SelectedItems
        ///
        /// SelectedItems Attached Dependency Property
        ///
        public static readonly DependencyProperty SelectedItemsProperty =
        DependencyProperty.RegisterAttached("SelectedItems", typeof(IList),
        typeof(ListBoxSelectedItemsAttachedProperty),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
        new PropertyChangedCallback(OnSelectedItemsChanged)));

        public static IList GetSelectedItems(DependencyObject d)
        {
            return (IList)d.GetValue(SelectedItemsProperty);
        }

        public static void SetSelectedItems(DependencyObject d, IList value)
        {
            d.SetValue(SelectedItemsProperty, value);
        }

        private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ListBox miLb = (ListBox)d;
            miLb.SelectionChanged += listBox_SelectionChanged;
        }

        private static void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ListBox miLg = (ListBox)sender;
            //Get list box's selected items.
            IEnumerable miDgSelectedItems = miLg.SelectedItems;
            //Get list from model
            IList ModelSelectedItems = GetSelectedItems(miLg);

            //Update the model
            ModelSelectedItems.Clear();

            if (miLg.SelectedItems != null)
            {
                foreach (var item in miLg.SelectedItems)
                    ModelSelectedItems.Add(item);
            }
            SetSelectedItems(miLg, ModelSelectedItems);
        }
        #endregion
    }

И в axml оно используется таким образом, например, вa Listbox:

Behaviors:ListBoxSelectedItemsAttachedProperty.SelectedItems="{Binding MyPropertyInViewModel}"

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

public class SelectedItemsBehavior : Behavior<MultiSelector>
    {
        protected override void OnAttached()
        {
            AssociatedObject.SelectionChanged += AssociatedObjectSelectionChanged;
        }
        protected override void OnDetaching()
        {
            AssociatedObject.SelectionChanged -= AssociatedObjectSelectionChanged;
        }

        void AssociatedObjectSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            List<object> selectedItemList = AssociatedObject.SelectedItems.Cast<object>().ToList();
            ObservableCollection<object> selectedItems = new ObservableCollection<object>(selectedItemList);
            SelectedItems = selectedItems;
        }
        public ObservableCollection<object> SelectedItems
        {
            get { return (ObservableCollection<object>)GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }
        public static readonly DependencyProperty SelectedItemsProperty =
            DependencyProperty.Register("SelectedItems"
                , typeof(ObservableCollection<object>)
                , typeof(SelectedItemsBehavior)
                ,
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    }

И в axml используется таким образом, например, в DataGrid:

<i:Interaction.Behaviors>
    <Behaviors:SelectedItemsBehavior SelectedItems="{Binding MyPropertyInViewModel}" />
</i:Interaction.Behaviors>

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

Спасибо.

1 Ответ

0 голосов
/ 19 ноября 2018

Существует два основных способа реализации прикрепленного поведения в WPF. Вы можете создать вложенное свойство и применить к нему PropertyChangedCallback, которое выполняет какое-либо действие или расширяет DependencyObject, к которому оно прикреплено, когда изменяется значение свойства зависимости.

Другой способ - создать класс из System.Windows.Interactivity.Behavior<T>. Обычно это называется «смешанным» поведением и обеспечивает лучший способ инкапсулировать функциональность поведения по сравнению с созданием присоединенного свойства с обратным вызовом. Поведения Blend также более удобны для проектирования, так как их можно легко прикрепить к визуальным элементам в пользовательском интерфейсе с помощью функции перетаскивания в Blend, и они также предлагают простой и понятный способ присоединения и освобождения обработчиков событий с помощью OnAttached и OnDetaching методов. Основным недостатком является то, что вы не можете применять такие виды поведения в установщиках стилей.

Так что, если вам нужно иметь возможность прикрепить свое поведение в Style, используйте присоединенное свойство. В противном случае я бы предпочел использовать поведение Blend. В этом блоге приведен пример привязки к свойствам, доступным только для чтения , если вам интересно.

...