-
Notifications
You must be signed in to change notification settings - Fork 678
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TreeViewItem doesn't update IsSelected in SelectionMode=Multiple when clicking on Checkbox or content #125
Comments
I tried some hacky workarounds to see if I could use Multiple mode, but everytime I changed my |
Thanks for the report! Our team is on holiday break right now but we'll take a look when we return! |
I took a quick look at this and the culprit here seems to be the call to ListView's::PrepareContainerForItemOverride call here. When we data bind a collection to the TreeView (using ItemsSource), set the TreeView to SelectionMode::Multiple and set a (two-way) bound IsSelected property in our bound data collection items, this call to ListView's PrepareContainerForItemOverride() sets the IsSelected property of the bound data item to This happens because we set the SelectionMode of the ListView to As such, I wrote a quick guard against this call when we are using data binding in SelectionMode::Multiple: // Don't call ListView's base method when we are using data binding and are in SelectionMode::Multiple
if (!IsContentMode() || !m_isMultiselectEnabled)
{
__super::PrepareContainerForItemOverride(element, item);
} With additional logic to handle checkbox selection and updating the data-bound IsSelected properties, using IsSelected property binding to select treeview items now works partly. The issue I'm currently facing is this one: Suppose we have the following data collection we bind to: private ObservableCollection<TreeViewItemSource> PrepareItemsSource(bool expandRootNode = false)
{
var root0 = new TreeViewItemSource() { Content = "Root.0", IsSelected = true };
var root = new TreeViewItemSource() { Content = "Root", Children = { root0 } };
// TestTreeViewItemsSource
return new ObservableCollection<TreeViewItemSource>{root};
} We have a root item (Root) with one child (Root.0). The child has its IsSelected property set to <muxcontrols:TreeView
ItemsSource="{x:Bind TestTreeViewItemsSource}"
SelectionMode="Multiple">
<muxcontrols:TreeView.ItemTemplate>
<DataTemplate x:DataType="local:TreeViewItemSource">
<muxcontrols:TreeViewItem
ItemsSource="{x:Bind Children}"
Content="{x:Bind Content}"
IsSelected="{x:Bind IsSelected, Mode=TwoWay}"/>
</DataTemplate>
</muxcontrols:TreeView.ItemTemplate>
</muxcontrols:TreeView> (Code is a slightly modified version of the MUXControlsTestApp TreeView test code.) Important here is that root TreeViewItem is not set to be expanded (IsExpanded = false). The expected look is this: However, the actual behavior is this one: We first need to actually expand the root item for it to be marked as selected. This is the case because there is no TreeViewItem created for its child (Root.0) yet. A TreeViewItem is only created for the child once we request it to be shown (by expanding its parent). Once it is created, the registered property changed callback for its IsSelected property is called which in turn updates the selection state of its parent and its children (if any). Thus, Root will be set to selected state. So then, the question I now have...how can we proceed from here? Seems like we currently need the TreeViewItem's children to be able to set the correct selection state on its parent yet we don't have those available when the parent is not in an expanded state initially. |
I spent the whole day wrapping my head around what seems to be the same issue as this one until I finally found this issue. Would be awesome if this could be fixed at some point - looks like the issue is already pretty old. If you need a repro project, let me know and I can make one.
|
@Felix-Dev's observation is correct, the rudimentary cause of this problem is the underlying ListView's selection mode being set to none. Skipping the "super" call will cause bunch of other unexpected behaviors. To fix the issue we probably need to either make changes in ListView to make it comply with TreeView or swap out the underlying implementation using ItemsRepeater. The current workaround is using selection Apis without data binding. |
Thanks, that workaround seems to work. I can still use databinding, but have to manually add the item to the |
@tipa What do you mean by "I can still use databinding"? Because when I do This is not the case for IsExpanded (IsExpanded="{x:Bind IsOpened, Mode=TwoWay}"). That works as expected. @kaiguo |
This is still a issue 17.02.2022. Please fix! |
It is annoing that I can make a workaround to databind the threeview this easy:
|
This issue is causing a big roadblock for my ongoing project... please fix it |
How is this still an issue after four years? please fix it. |
This is ridiculous. |
Here is the workaround I came up with: I have a class
Then in
This spins up a thread that constantly checks what items are selected, and updates a selected prop on what you are binding to. It's inefficient and destroys the purpose of using MVVM, but the best I could come up with, because the selection events also don't work / aren't comprehensive. |
Anyone fix this? |
Here's a workaround sample app just in case. |
Bump, is anyone looking into this issue or has it gone stale? @jevansaks |
Same here, broken, but with UWP almost done, not surprising. |
Using WinUI3. Same issue... is this not a key component to a working tree view using MVVM? any status update? |
Focus might work |
In addition, SelectionChanged is not fired when SelectedItems is changed in multiple selection mode. |
This component is so bad, I have actually done my own, based on ListView, to keep things moving. Avoid TreeView. |
WinUI 3 now has a SelectionChanged event we can use. So, at least there's that. |
The IsSelected property with Mode=TwoWay is still not working. Is this something they are going to fix in the short term? It would be ideal if SelectedItems had both set and get, rather than just get. Additionally, it would be useful to enable the IsEnabled property specifically for the checkbox. |
Describe the bug
When you have a
TreeView
usingItemsSource
binding and set toSelectionMode="Multiple"
, theIsSelected
property is not changed when clicking on the checkbox. Also, the checkbox is not changed when clicking on the item, either.Steps to reproduce the bug
Steps to reproduce the behavior:
SelectionMode="Multiple"
toTreeView
IsSelected="{x:Bind IsSelected,Mode=TwoWay}"
to theTreeViewItem
Debug.WriteLine($"Selected changed: {value}");
to theset
statement forIsSelected
in the code-behind file. Include using statement for Debug.Expected behavior
The debug output should show
Selected changed: true
when the checkbox is checked andSelected changed: false
when unchecked. Also, the checkbox should be checked/unchecked when the content of theTreeViewItem
is toggled.Screenshots
Version Info
NuGet package version:
Microsoft.UI.Xaml v2.0.181018003.1
Windows 10 version:
Device form factor:
Additional context
The text was updated successfully, but these errors were encountered: