Custom Command Not Triggering in TreeView ItemContextFlyout

I have a user control that includes a Syncfusion TreeView. Following the Syncfusion online examples for a WinUI TreeView (https://help.syncfusion.com/winui/treeview/contextflyout), the control has a data context:

    <UserControl.DataContext>

        <viewmodel:MyViewModel />

    </UserControl.DataContext>


The exact syncfusion example XAML code for attaching to a command in the data context leads to a compile error in my code for the data context. Because of the data context noted above, however, I only needed to include the name of the command in MyViewModel, which is ExpandCommand. For Example:

                    <MenuFlyoutItem

                        x:Name="Expand"

                        Command="{Binding ExpandCommand}"

                        CommandParameter="{Binding}"

                        Text="Expand" />


In the viewmodel, I have:

        public MyViewModel()

        {

            ExpandCommand = new DelegateCommand<object>(ExecuteExpandCommand, CanExecuteExpandCommand);

        }

        public ICommand ExpandCommand { get; set; }

        private bool CanExecuteExpandCommand(object obj)

        {

            if (obj is not TreeViewItemContextFlyoutInfo itemContextFlyoutInfo)

                return false;

            if (itemContextFlyoutInfo.Node.HasChildNodes)

                return true;

            return false;

        }


        private static void ExecuteExpandCommand(object obj)

        {

            if (obj is not TreeViewItemContextFlyoutInfo itemContextFlyoutInfo)

                return;

            itemContextFlyoutInfo.TreeView.ExpandNode(itemContextFlyoutInfo.Node);

        }


This all seems to coincide with the Syncfusion examples, but for some reason, the command is not triggering at all. I've tried using breakpoints, but nothing. What might be missing?


Thanks for the help.


3 Replies

MA Manikanda Akash Munisamy Syncfusion Team October 8, 2024 02:54 PM UTC

Hi Edward, 

We have reviewed your scenario where you faced a compilation error when UserControl.DataContext in given in XAML for a UserControl containing SfTreeView. We tried to replicate the issue on our end but were unable to do so. 

However, there's an alternative way to provide DataContext in XAML that you can try. This method involves defining the ViewModel in the resources and then binding it as the Source for both ItemsSource and commands. We’ve attached a sample demonstrating this approach for your reference.


CodeSnippet:
<UserControl.Resources>
  <local:ViewModel x:Key="ViewModel"/>
</UserControl.Resources> 
<Grid>      <treeView:SfTreeView x:Name="treeView" Width="400" Height="500"                         
                        ChildPropertyName="Childs" IsAnimationEnabled="True"          
                         SelectionMode="Multiple" FullRowSelect="True"
                         ItemsSource="{Binding Nodes1, Source={StaticResource ViewModel}}">
         <treeView:SfTreeView.ItemContextFlyout>
             <MenuFlyout>
                 <MenuFlyoutItem x:Name="Expand" Text="Expand" CommandParameter="{Binding }" Command="{Binding ExpandCommand, Source={StaticResource ViewModel}}" />
             </MenuFlyout>
         </treeView:SfTreeView.ItemContextFlyout>
     </treeView:SfTreeView>
 </Grid>
 
This approach provides a clear way to bind your ViewModel to controls and commands directly within XAML, avoiding the need to set the DataContext separately in code-behind.

If we’ve misunderstood your requirements or if further assistance is needed, please provide additional details. This will help us tailor the solution more accurately.

Regards,
Manikanda Akash


Attachment: SfTreeView_Net60_508f1597.zip



ED Edward October 8, 2024 07:09 PM UTC

I ended up using IRelayCommand from the CommunityToolkit.Mvvm package and x:Bind for the XAML binding, which works in my case. My ViewModel is defined in the code behind, but it could be bound in the XAML.


In XAML:

                    <MenuFlyoutItem

                        x:Name="Expand"

                        Command="{x:Bind ViewModel.ExpandNodeCommand}"

                        CommandParameter="{Binding}"

                        Text="Expand" />


In the ViewModel:

        public IRelayCommand ExpandNodeCommand { get; }


        public WBSViewModel()

        {

            ...

            ExpandNodeCommand = new RelayCommand<object>(ExecuteExpandCommand, CanExecuteExpandOrCollapseCommand);

        }


        private bool CanExecuteExpandOrCollapseCommand(object obj) {...}

        private static void ExecuteExpandCommand(object obj) {...}





MA Manikanda Akash Munisamy Syncfusion Team October 9, 2024 01:53 PM UTC

Hi Edward,

We have reviewed your code, and it is another viable approach to bind the value to a command in XAML. We have also tested it in our sample, and the ExecuteCommand is executed correctly.


If you have any further queries or need assistance, please feel free to contact us.

Regards,
Manikanda Akash

Loader.
Up arrow icon