2012-01-27 2 views
2

Я использую Caliburn micro (1.3)/MVVM и Silverlight. Когда я обновляю источник RadGridView, я теряю выбранные элементы. Я нашел блог о реализации поведения для сохранения выбранных элементов при реализации MVVM. Я могу получить выбранные элементы, но я не могу установить их обратно, когда обновляется источник. Может ли кто-нибудь объяснить мне, как реализовать это, используя caliburn.micro и RadGridVIew? Я думаю, что лучший способ - создать микросхему caliburn, но я могу найти ссылку для создания соглашения для selectedItem, а не SelectedItems.Сохранить выбранные элементы при использовании caliburn.micro/Telerik RadGridView/Silverlight

Может ли кто-нибудь показать мне, как это сделать? Я попробовал следующее, но это не сработает.

private static void SetRadGridSelecteditemsConventions() 
    { 
     ConventionManager 
      .AddElementConvention<DataControl>(DataControl.ItemsSourceProperty, "SelectedItem", "SelectionChanged") 
      .ApplyBinding = (viewModelType, path, property, element, convention) => 
           { 
            ConventionManager.SetBinding(viewModelType, path, property, element, convention, DataControl.ItemsSourceProperty); 

            if (ConventionManager.HasBinding(element, DataControl.SelectedItemProperty)) 
             return true; 

            var index = path.LastIndexOf('.'); 
            index = index == -1 ? 0 : index + 1; 
            var baseName = path.Substring(index); 
            foreach (var selectionPath in 
             from potentialName in ConventionManager.DerivePotentialSelectionNames(baseName) 
             where viewModelType.GetProperty(potentialName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance) != null 
             select path.Replace(baseName, potentialName)) 
            { 
             var binding = new Binding(selectionPath) { Mode = BindingMode.TwoWay }; 
             BindingOperations.SetBinding(element, DataControl.SelectedItemProperty, binding); 
            } 
            return true; 
           }; 
    } 

Спасибо, Stephane

ответ

1

Вы должны использовать поведение для этого, так как свойство SelectedItems только для чтения. Для этого Telerik имеет example, только пример не относится к caliburn.micro. Если добавить следующий класс в проект:

public class MultiSelectBehavior : Behavior<RadGridView> 
{ 
    public INotifyCollectionChanged SelectedItems 
    { 
     get { return (INotifyCollectionChanged)GetValue(SelectedItemsProperty); } 
     set { SetValue(SelectedItemsProperty, value); } 
    } 

    public static readonly DependencyProperty SelectedItemsProperty = 
     DependencyProperty.Register("SelectedItems", typeof(INotifyCollectionChanged), typeof(MultiSelectBehavior), new PropertyMetadata(OnSelectedItemsPropertyChanged)); 


    private static void OnSelectedItemsPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs args) 
    { 
     var collection = args.NewValue as INotifyCollectionChanged; 
     if (collection != null) 
     { 
      collection.CollectionChanged += ((MultiSelectBehavior)target).ContextSelectedItems_CollectionChanged; 
     } 
    } 

    protected override void OnAttached() 
    { 
     base.OnAttached(); 

     AssociatedObject.SelectedItems.CollectionChanged += GridSelectedItems_CollectionChanged; 
    } 

    void ContextSelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     UnsubscribeFromEvents(); 

     Transfer(SelectedItems as IList, AssociatedObject.SelectedItems); 

     SubscribeToEvents(); 
    } 

    void GridSelectedItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     UnsubscribeFromEvents(); 

     Transfer(AssociatedObject.SelectedItems, SelectedItems as IList); 

     SubscribeToEvents(); 
    } 

    private void SubscribeToEvents() 
    { 
     AssociatedObject.SelectedItems.CollectionChanged += GridSelectedItems_CollectionChanged; 

     if (SelectedItems != null) 
     { 
      SelectedItems.CollectionChanged += ContextSelectedItems_CollectionChanged; 
     } 
    } 

    private void UnsubscribeFromEvents() 
    { 
     AssociatedObject.SelectedItems.CollectionChanged -= GridSelectedItems_CollectionChanged; 

     if (SelectedItems != null) 
     { 
      SelectedItems.CollectionChanged -= ContextSelectedItems_CollectionChanged; 
     } 
    } 

    public static void Transfer(IList source, IList target) 
    { 
     if (source == null || target == null) 
      return; 

     target.Clear(); 

     foreach (var o in source) 
     { 
      target.Add(o); 
     } 
    } 
} 

Такое поведение заботится о синхронизации между коллекционными RadGridView.SelectedItems и MultiSelectBehavior.SelectedItems.

Теперь мы должны иметь ObservableCollection в ViewModel

//Collection holding the selected items 
    private ObservableCollection<object> selectedGridItems; 
    public ObservableCollection<object> SelectedGridItems 
    { 
     get 
     { 
      if (selectedGridItems == null) 
       selectedGridItems = new ObservableCollection<object>(); 

      return selectedGridItems; 
     } 
     set 
     { 
      if (selectedGridItems == value) return; 
      selectedGridItems = value; 
      NotifyOfPropertyChange(() => SelectedGridItems); 
     } 
    } 

    //Deselect all selected items in the gridview 
    public void ClearSelectedGridItems() 
    { 
     SelectedGridItems.Clear(); 
    } 

Последняя вещь связывают поведение с точки зрения

<telerik:RadGridView x:Name="CustomLogs" AutoGenerateColumns="true" SelectionMode="Extended"> 
     <i:Interaction.Behaviors> 
      <local:MultiSelectBehavior SelectedItems="{Binding SelectedGridItems}"/>     
     </i:Interaction.Behaviors>     
    </telerik:RadGridView> 

Вот это, надеюсь, это поможет вам!

Смежные вопросы