0

I'm using a third party .dll which contains a type of object called Layer. I have a collection of these layers in my viewmodel. In my view, I have a TreeView whose ItemsSource is bound to the collection of layers. I also have a checkbox with each item.

I want to somehow get the all of the checked Layer items.

Normally I would have just make a public boolean property called IsChecked in the object's class, but Layer does not have a property for that.

Here's the xaml:

<TreeView Grid.Row="1" Grid.Column="0">
    <TreeViewItem Header="Shape Files" ItemsSource="{Binding Layers}" >
        <TreeViewItem.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <CheckBox Content="{Binding Name}" />
                </StackPanel>
            </DataTemplate>
        </TreeViewItem.ItemTemplate>
    </TreeViewItem>
</TreeView>

Here's the view model:

public ObservableCollection<Layer> Layers
{
    get { return mapModel.Layers; }
    set { mapModel.Layers = value; OnPropertyChanged("Layers"); }
}

And here's an example of what this looks like:

enter image description here

I know one way would be to have the checked function of the checkboxes bind to a command, with the item itself being sent as a command parameter. Is that really the best way to do this though?

pfinferno
  • 1,779
  • 3
  • 34
  • 62
  • 1
    does layer have a property "IsCurrentlySelected"? if not, you could make a class "SelectableLayer" that derives from Layer. then you can change the TreeView.ItemContainerTemplate in order to bind TreeViewItem.IsSelected to SelectableLayer.IsCurrentlySelected. then you can just iterate through your collection and take all layers that are selected. – Milan Jan 25 '18 at 18:19
  • It does not unfortunately. I did try creating a Layer class that derived from Layer, but there were a lot of problems. Mainly because there are a lot of different types of "Layers" that also derive from "Layer", all of which need to be added to the ObservableCollection I have in the view model. When I changed the `Layers` collection to my derived Layer class, it stopped working. – pfinferno Jan 25 '18 at 18:22
  • You might try attached property approach, like [this SO post's answer](https://stackoverflow.com/questions/5832208/wpf-attached-property-data-binding) explains. – Alex Seleznyov Jan 25 '18 at 19:19
  • 1
    perhaps another option is to make a class LayerContainer, which would have a property of type Layer inside. so you now have an ObservableCollection, and that class would have IsCurrentlySelected? other than that, i suspect the only thing left is what you meant to begin with(commands) :/ – Milan Jan 25 '18 at 19:23

1 Answers1

1

Bind another ObservableCollection<Layer> object to TreeView.Tag. Register CheckBox's Checked and Unchecked event. In code behind, the sender's DataContext property should contain a Layer object. Add or remove it from the ObservableCollection<Layer> object that bound to TreeView.Tag depend on which event you are handling. You can access the ObservableCollection<Layer> object from view model any time, you will alway get all the Layer objects that has been selected.

In my opinion, this solution is most effective one, and dosn't voilate any MVVM principle. If you think use a type that was defined in lower layer in view is not acceptable, cast TreeView.Tag to a IList interface could simply avoid that.

Alex.Wei
  • 1,798
  • 6
  • 12
  • I have update my answer to fix the incorrect part about where `Layer` object will be contained to. I didn't read the xaml carefully and just said the `Layer` object should be contained in a `TreeViewItem.DataContext`. Any that was a obvious mistake. – Alex.Wei Jan 26 '18 at 14:48