2

Caliburn micro(1.3)/MVVM と Silverlight を使用しています。itemsource RadGridView を更新すると、選択した項目が失われます。MVVM実装時に選択項目を保存する動作を実装しているブログを見つけました。選択したアイテムを取得できますが、アイテムソースが更新されると元に戻すことはできません。caliburn.micro と RadGridView を使用してこれを実装する方法を教えてもらえますか? 最善の方法は caliburn マイクロ コンベンションを作成することだと思いますが、selectedItems ではなく、selectedItem の規約を作成するためのリファレンスしか見つかりません。

誰かがこれを達成する方法を教えてもらえますか? 以下を試してみましたが、うまくいきません。

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

ありがとう、ステファン

4

1 に答える 1

1

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 の間の同期を処理します。

ここで、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>

それだけです。お役に立てば幸いです。

于 2012-03-07T16:18:45.217 に答える