使用caliburn.micro / Telerik RadGridView / Silverlight时保存所选项目

时间:2012-01-27 21:50:00

标签: caliburn.micro radgridview

我正在使用Caliburn micro(1.3)/ MVVM和Silverlight。当我更新itemsource RadGridView时,我丢失了所选的项目。我发现了一个关于在实现MVVM时实现保存所选项的行为的博客。我可以获取所选项目,但是一旦刷新了itemsource,我就无法将它们设置回来。有人能告诉我如何使用caliburn.micro和RadGridVIew实现这一点吗?我认为最好的方法是创建一个caliburn微型约定,但我只能找到为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 个答案:

答案 0 :(得分: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之间的同步。

现在我们需要在ViewModel中有一个ObservableCollection

    //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>

多数民众赞成,希望它可以帮到你!