Сохранить выбранные элементы при использовании caliburn.micro / Telerik RadGridView / Silverlight - PullRequest
2 голосов
/ 28 января 2012

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

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

  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;
                                };
    }

Спасибо, Стефан

1 Ответ

1 голос
/ 07 марта 2012

Для этого следует использовать поведение, поскольку свойство SelectedItems доступно только для чтения. Для этого у Telerik есть пример , только пример не относится к 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>

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

...