This is a migrated thread and some comments may be shown as answers.

IsSelectable support

9 Answers 147 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Thorsten
Top achievements
Rank 1
Thorsten asked on 30 Oct 2010, 06:13 PM
Hi,

I'm using the RadTreeView in a MVVM scenario.
Depending on the model's IsSelectable property the corresponding item should be either selectable by the user or not.
Since this doesn't seem to be supported by the RadTreeViewItem container itself (which would be a nice new feature ;)),
the only way I found in this case is to listen on the container's PreviewSelected event and setting the "e.Handled" value to "true" if the item shouldn't be selectable.
So it looks like:

void RadTreeView_PreviewSelected(object sender, RadRoutedEventArgs e)
{
  var item = e.GetItem<IMyModel>(); // extension helper method
 
  // check item that will be selected   
  if (item != null && !item.IsSelectable)
    e.Handled = true;


But this results in a major drawback:
Upon canceling selection of the new item 'X', i'm loosing the currently selected item.
Afterwards the item 'X' has the focus rectangle and the selected item is null.
So the question is:
Is there a possiblity to cancel the selection of a new item without loosing the previous selection ?

It tried to hook the PreviewSelected, PreviewUnselected, Unselected, Selected events.
But even if set an additional flag on "PreviewSelected" which indicates that I want to revert/ignore the next unselection, I'm out of luck.
- PreviewUnselected is called before PreviewSelected => I can't determine whether to cancel or not since i don't know the future ;)
- Unselected gets actually called directly after PreviewSelected, but the RadTreeView's SelectedItem is still unchanged.
  Setting the "e.Handled" value to "true" won't change anything.
 
The second question would be:
Upon the "Unselected"-Event shouldn't the treeview's currently selected item be either the next selected item or null ?

Thanks in advance

Thorsten Klingert

9 Answers, 1 is accepted

Sort by
0
Miro Miroslavov
Telerik team
answered on 03 Nov 2010, 10:22 AM
Hello Thorsten Klingert,

 You could bind the IsEnabled property of the RadTreeViewItem to the IsSelectable, thus the item will be disabled and restricted from selection.
Please let me know if this is not an option for you.

Best wishes,
Miro Miroslavov
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Thorsten
Top achievements
Rank 1
answered on 03 Nov 2010, 10:42 AM
Hi,

thanks for the response, but the disabling the item isn't an option.
I'm using hierarchical data where some layers are selectable and others not.
Even if a parent item is not selectable their childs might be.
Disabling the parent item does not allow any child selection.

With kind regards

Thorsten Klingert
0
Tina Stancheva
Telerik team
answered on 05 Nov 2010, 05:21 PM
Hi Thorsten Klingert,

Can you please have a look at the attached example and let me know if this is close to what you had in mind?

Thank you in advance.

All the best,
Tina Stancheva
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Thorsten
Top achievements
Rank 1
answered on 05 Nov 2010, 10:25 PM
Hi,

so once again, thanks for the response and the sample.

I attached a modified version of your project to the feature request thread: http://www.telerik.com/account/support-tickets/view-ticket.aspx?threadid=363785

From a surface look, you've exactly hit what i had in mind.

After looking at the code I'm a bit puzzled why the re-selection of the last deselected item in this case works at all.

Since I've done actually zero with silverlight, I attached the poor man's tracer, a listbox, to the main view.
It turns out that on PreviewSelected, the SelectedItem of the tree view is still the one stored to the unselectedItem variable within the last PreviewUnselected call.
So assigning the same item as selected item again shouldn't normally change anything but in this case it does.
To make things even more curious, the tree view's selected item is NULL after the assignment of the last unselected item which clearly wasn't NULL.

So also it seems to work as intended, i discovered two drawbacks:
1. The cancelation results in 2 Unselected and 2 Selected-events being raised for the same, untouched item.
2. If multiselection is enabled and lets say two valid items are selected, ctrl+click on a non-selectable item messes up the SelectedItems collection of the treeview. It now contains the same items twice.

I think the only way to handle such a scenario without side effects is a direct support via a RadTreeViewItem property.

With kind regards

Thorsten Klingert

 
0
Hristo
Telerik team
answered on 08 Nov 2010, 07:06 PM
Hi Thorsten,

I can understand the frustration you are experiencing with our tree view and its selection. However there is a logical explanation to your question, and it is based on the fact that you are trying to change the selected item inside the PreviewSelected event. The tree view internally does not select the required element immediatelly. Instead it remembers which item should be selected and selects it in a later step.

So when calling the treeView.SelectedItem = unselecteItem the code marks which item should be selected and makes the currently selected item to be Null. Unfortunately this internal logic is called just before your check for null. Then this internal logic is called for second time (due to the mouse click that made the selection change event). In a third step after the PreviewSelected event has passed the tree view changes the selected item (the third preview selected in the output below) and fires Unselected and Selected events.

You can take a look at the following code which is a slight modification of yours:

private void treeView_PreviewUnselected(object sender, Telerik.Windows.RadRoutedEventArgs e)
{
    unselectedItem = e.Source as RadTreeViewItem;
    //this.ListBox1.Items.Add("preview unselected: " + GetDataItem(e.Source).Name);
    Debug.WriteLine("preview unselected: " + GetDataItem(e.Source).Name);
}
 
private void treeView_PreviewSelected( object sender, Telerik.Windows.RadRoutedEventArgs e )
{
    //this.ListBox1.Items.Add("preview selected--------------Begin");
    Debug.WriteLine("preview selected--------------Begin");
    RadTreeViewItem itemContainer = e.Source as RadTreeViewItem;
    if (itemContainer == null)
    {
        this.ListBox1.Items.Add("itemContainer == null");
    }
 
    DataItem item = itemContainer.Item as DataItem;
    if (item == null)
    {
        this.ListBox1.Items.Add("item == null");
    }
 
    if (!item.isSelectable)
    //if ( !( item.Item as DataItem ).isSelectable )
    {
        e.Handled = true;
 
        //this.ListBox1.Items.Add("preview selected (cancel, item to cancel): " + GetDataItem(e.Source).Name);
        //this.ListBox1.Items.Add("preview selected (cancel, pre-revert, current selected item): " + GetDataItem(treeView.SelectedItem).Name);
        //this.ListBox1.Items.Add("preview selected (cancel, pre-revert, last unselected item): " + GetDataItem(unselectedItem).Name);
 
        Debug.WriteLine("preview selected (cancel, item to cancel): " + GetDataItem(e.Source).Name);
        Debug.WriteLine("preview selected (cancel, pre-revert, current selected item): " + GetDataItem(treeView.SelectedItem).Name);
        Debug.WriteLine("preview selected (cancel, pre-revert, last unselected item): " + GetDataItem(unselectedItem).Name);
                 
        //treeView.SelectedItem = unselectedItem;
 
        //this.ListBox1.Items.Add("preview selected (cancel, post-revert, current selected item): " + (treeView.SelectedItem == null ? "<null>" : GetDataItem(treeView.SelectedItem).Name));
        Debug.WriteLine("preview selected (cancel, post-revert, current selected item): " + (treeView.SelectedItem == null ? "<null>" : GetDataItem(treeView.SelectedItem).Name));
    }
    else
    {
        //this.ListBox1.Items.Add("preview selected Selectable item: " + item.Name);
        Debug.WriteLine("preview selected Selectable item: " + item.Name);
        this.mustStop = false;
    }
    //this.ListBox1.Items.Add("preview selected--------------End");
    Debug.WriteLine("preview selected--------------End");
}
 
void treeView_Unselected(object sender, Telerik.Windows.RadRoutedEventArgs e)
{
    int i = 3;
    //this.ListBox1.Items.Add("unselected: " + GetDataItem(e.Source).Name);
    Debug.WriteLine("unselected: " + GetDataItem(e.Source).Name);
}
 
void treeView_Selected(object sender, Telerik.Windows.RadRoutedEventArgs e)
{
    int i = 3;
    //this.ListBox1.Items.Add("selected: " + GetDataItem(e.Source).Name);
    Debug.WriteLine("selected: " + GetDataItem(e.Source).Name);
}

The code above produces the following output when "Item 0" is selected and you click on "Item 0.0":

preview unselected: Item 0
preview selected--------------Begin
preview selected (cancel, item to cancel): Item 0.0
preview selected (cancel, pre-revert, current selected item): Item 0
preview selected (cancel, pre-revert, last unselected item): Item 0
preview selected--------------Begin
preview selected Selectable item: Item 0
preview selected--------------End
preview selected (cancel, post-revert, current selected item): <null>
preview selected--------------End
unselected: Item 0
preview selected--------------Begin
preview selected Selectable item: Item 0
preview selected--------------End
selected: Item 0

Hope this info is helpful. Also there is another event you can use to implement the required functionality. Attach a handler to the SelectionChanged event that is fired after all 4 events (PreviewUnselected, Unselected, PreviewSelected, Selected). The following code below demonstrates that approach:

private void treeView_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangedEventArgs e)
{
    int i = 1;
    if (!this.mustReverSelection)
    {
        foreach (DataItem item in e.AddedItems)
        {
            if (item.isSelectable == false)
            {
                this.mustReverSelection = true;
                break;
            }
        }
    }
 
    if (this.mustReverSelection)
    {
        this.mustReverSelection = false;
 
        foreach (DataItem itemToRemove in e.AddedItems)
        {
            this.treeView.SelectedItems.Remove(itemToRemove);
        }
 
        foreach (DataItem itemToAdd in e.RemovedItems)
        {
            this.treeView.SelectedItems.Add(itemToAdd);
        }
    }
}
private bool mustReverSelection = false;

Please let us know if you need more help or information about our controls.


All the best,
Hristo
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Thorsten
Top achievements
Rank 1
answered on 09 Nov 2010, 08:35 AM
Hi,

thanks for the response.

For a single selection scenario, I'm currently using a mix of both.
bool _revertNextUnselection;
private void Tree_PreviewSelected( object sender, RadRoutedEventArgs e )
{
    var item = e.GetItem<IMyItem>( );
    if ( item != null && !item.IsSelectable ) // abort selection.
    {
        e.Handled = true;
        this._revertNextUnselection = this._tree.SelectedItem != null;
    }
 
}
private void Tree_SelectionChanged( object sender, SelectionChangedEventArgs e )
{
    if ( this._revertNextUnselection )
    {
        this._revertNextUnselection = false;
        // revert last single unselection.
        if ( this._tree.SelectedItem == null
                && e.AddedItems.Count == 0
                && e.RemovedItems.Count == 1 )
            this._tree.SelectedItem = e.RemovedItems[0];
    }
}

Regarding multiselection:
Is the sideeffect I mentioned below ( the duplicates within the SelectedItems collection ) considered as bug ?
0
Hristo
Telerik team
answered on 09 Nov 2010, 12:06 PM
Hi Thorsten,

I was not able to reproduce the duplicated items in SelectedItems collection. Can you provide us a step by step scenario that reproduces the issue with your project.

Regarding your question: the answer should be yes.

Sincerely yours,
Hristo
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Thorsten
Top achievements
Rank 1
answered on 09 Nov 2010, 08:14 PM
Hi,

for sure, if you run the previously attached project (http://www.telerik.com/ClientsFiles/229138_289938-treeviewcontainerbindings-modified.zip), do the following:

1. click on Item 0.0.0
2. click on Item 0.0.1
3. ctrl+click on Item 0.0.0
4. ctrl+click on Item 0.0
5. hit the dump selected items button.

The output should now look like the attached screenshot and the Item 0.0.0 should now be twice within the SelectedItems collection.

With kind regards

Thorsten
0
Accepted
Hristo
Telerik team
answered on 11 Nov 2010, 09:57 AM
Hi Thorsten,

Thank you for providing us the steps to reproduce. Actually the reason this is happening is that SelectedItems collection contains DataItem object as well as RadTreeViewItem objects. This behavior is incorrect. When the tree view is data bound it should contain only business objects (DataItem(s)). I logged the bug in our public issue tracking system under the following link: http://www.telerik.com/support/pits.aspx#/public/wpf/3959


Also there is a record in our PITS for IsSelectable property. You can vote for it here:
http://www.telerik.com/support/pits.aspx#/public/silverlight/484

Finally, I'm giving you 1000 telerik points for finding bug in our tree view.

All the best,
Hristo
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Tags
TreeView
Asked by
Thorsten
Top achievements
Rank 1
Answers by
Miro Miroslavov
Telerik team
Thorsten
Top achievements
Rank 1
Tina Stancheva
Telerik team
Hristo
Telerik team
Share this question
or