I am trying to get the selected item from my TreeView but having some problem. I am following MVVM archetecture. My ViewModel contains a collection of a class which is in my Model. So I have binded the ItemSource of TreeView with that collection. I want to bind the selectedItem of my TreeView to an item of the binded collection. HOw do I do that. Here is the code for SelectedItem and IsSelected Property.
private static sourceData _selectedItem = null;
/// <summary>
/// Selected Item in the tree
/// </summary>
public static sourceData SelectedItem
{
get { return _selectedItem; }
set
{
if (_selectedItem != value)
{
_selectedItem = value;
}
}
}
private bool _isSelected;
/// <summary>
/// Get/Set for Selected node
/// </summary>
public bool IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected != value)
{
_isSelected = value;
if (_isSelected)
{
SelectedItem = this;
OnPropertyChanged("IsSelected");
}
}
}
}
/// <summary>
/// Property changed event
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Property changed event handler
/// </summary>
/// <param name="propertyName"></param>
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = this.PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
When I debug this, int SelectedItem = this;
'this' pointer contains the collection to which my treeview is binded. I needed to have a SelectedDataSource so that I could assign it to the selected Item. How can I make my TreeView return me the selectedItem in the collection??
FYi, this is my XAML code for TreeView
<TreeView Margin="5,0,0,0" ItemsSource="{Binding SourceData}" Width="390">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding DataContext.IsSelected, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu Name="contextMenu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" >
<MenuItem Name="menuItem" Header="Rename" Command="{Binding RenameCommand}" />
</ContextMenu>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
P.S: If I write the above code in my Model, I get everything working perfectly fine. But I can not right the above code in Model, it has to be in VM.
Any help will be much appreciated.
Thanks
Further to the commentary on your question, the WPF TreeView gives some unique challenges to the MVVM developer, and among these is detecting the currently selected item. For this you can use attached behaviour. To begin, write a static class to contain the behaviour...
}
Then import the class's namespace into your Xaml (using xmlns). You can then declare a TreeView along these lines...
This 'wires' the TV behaviour to an ICommand in your VM. Finally, declare the ICommand in your VM...
public ICommand SelectedItemCommand { get; set; }
And initialize it...
And then implement your delegates...
When the user selects a TV item, your 'execute' delegate will get a boxed instance of the item, and you can unbox it and etc etc etc.
Note that the attached behaviour in this example assumes that the TV's lifetime is the same as the app, otherwise you have to unwire the attached behaviour. It also assumes that the TV ItemsSource is binding to something sensible.
That will solve the problem of getting the TV SelectedItem while remaining MVVM compliant (if such a thing as MVVM compliant exists).
The Relay Command class I used was taken from the linked article in MSDN. For reference purposes, here it is...
Use the MSDN link above to get more info about this class.