【发布时间】:2018-11-17 20:20:52
【问题描述】:
我必须选择在 ViewModel 中获取 SelectedItems。
这样的附加属性:
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中就是这样使用的,例如在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>
但我真的不知道附加属性和附加行为之间的区别,以及在 ViewModel 中获取 SelectedItems 的最佳选择是什么。
谢谢。
【问题讨论】:
-
为什么不将控件的 SelectedItems 属性绑定到视图模型属性?这就是 MVVM 的全部意义所在,并且比您展示的任何一个选项都简单得多(这对于要求来说都是多余的)
-
@AvrohomYisroel 这是不可能的,因为 SelectedItems 是只读的。因此,它是不可绑定的。正因为如此,每个人都在创造各种解决方法,比如问题中的两个解决方案。真的丑吗?是的。让我们感谢 Microsoft 从未修复此问题。
标签: c# wpf attached-properties attachedbehaviors