3

名前のObservableCollectionにバインドされているリストボックスがあります。リスト内の一部のアイテムには、アイテムが選択されたことを示すオン/オフを切り替えるチェックボックスがあります。

Master-Detailsの概念に従って、最初のリストボックスの選択されたアイテムからObservableCollectionを作成するにはどうすればよいですか?

(選択したアイテムコレクションを表示するDetailsViewのDataContextとしてMasterViewModelを使用する予定です。)

前もって感謝します!

4

1 に答える 1

5

ええ、私も以前にこれに出くわしました。ListBoxなどには「SelectedItem」という依存関係プロパティがありますが、「SelectedItems」(「s」付き)プロパティは1つとして実装されていません。

私が見つけた最もクリーンな解決策は、リストボックスをサブクラス化し、「SelectedItems」と呼ばれる独自の依存関係プロパティを作成することです。面白くありませんが、それが最善の解決策だと思います。

アップデート

まず、ViewModel:

class ViewModel : INotifyPropertyChanged
{
    // Set up our collection to be read from the View
    public ObservableCollection<String> Collection { get; private set; }

    // This collection will maintain the selected items
    public ObservableCollection<String> SelectedItems { get; private set; }

    public ViewModel()
    {
        // Instantiate
        this.Collection = new ObservableCollection<String>();
        this.SelectedItems = new ObservableCollection<String>();

        // Now let's monitor when this.SelectdItems changes
        this.SelectedItems.CollectionChanged += SelectedItems_CollectionChanged;

        // Fill our collection with some strings (1 to 10).
        // (1) Generate the numbers 1 - 10
        // (2) Convert each number to a string
        // (3) Cast into a list so we can use foreach 
        // (4) Add each item to the collection.
        Enumerable.Range(1, 10)
            .Select(number => number.ToString())   
            .ToList()                              
            .ForEach(this.Collection.Add);

        // Remember! Never reset the ObservableCollection.
        // That is, never say this.Collection = new... (or you'll break the binding).
        // instead use this.Collection.Clear(), and then add the items you want to add
    }

    void SelectedItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
        {
            foreach (String str in this.SelectedItems)
                System.Diagnostics.Debug.WriteLine("New item added {0}", str);

        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

次に、拡張ListBoxEx:

class ListBoxEx : ListBox
{
    // Use the 'new' keyword so that we 'hide' the base property.
    // This means that binding will go to this version of SelectedItems
    // rather than whatever the base class uses. To reach the base 'SelectedItems' property
    // We just need to use base.SelectedItems instead of this.SelectedItems
    // Note that we register as an observable collection.
    new DependencyProperty SelectedItemsProperty = 
        DependencyProperty.Register("SelectedItems", typeof(ObservableCollection<String>), typeof(ListBoxEx));

    // Accessor. Again, note the 'new'.
    new public ObservableCollection<String> SelectedItems
    {
        get { return (ObservableCollection<String>) GetValue(SelectedItemsProperty); }
        set { SetValue(SelectedItemsProperty, value); }
    }

    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        // Guard against ViewModel being null
        if (this.SelectedItems != null)
        {
            // Clear the list
            this.SelectedItems.Clear();

            // (1) On selection changed. Get the new base.SelectedItems
            // (2) Cast each item to a String ("Make a string collection")
            // (3) Cast to list, and use foreach to add each item to 
            // this.SelectedItems (note this is different from the original base.SelectedItems)
            base.SelectedItems.Cast<String>()
                .ToList()
                .ForEach(this.SelectedItems.Add);
        }
    }
}

そして最後に私たちの見解:

<Window.DataContext>
    <lol:ViewModel />
</Window.DataContext>
<Grid>
    <lol:ListBoxEx ItemsSource="{Binding Collection}" SelectedItems="{Binding SelectedItems}"
                   SelectionMode="Multiple"/>
</Grid>
于 2013-02-08T00:44:37.607 に答える