xamldata-bindingmodel-bindingwinui-3xbind

How to bind in WinUI 3 nested template binding to the view model?


I have a winui3 app that has responsive UI for screen like desktop, tablet and mobile. I have three template for that. and I used content Control inside the page within the Content Control there is Visual Manager that is used for Adoptive UI. the problem is that in my Datatemplate I have netsted data templates. like this?

<Page
    x:Class="TDBMS.Views.UsersView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ViewModels="using:TDBMS.ViewModels"
    xmlns:coreModels="using:TDBMS.Core.Models"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:TDBMS.Views"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    x:Name="PageRoot"
    mc:Ignorable="d">
    <Page.Resources>

     <XamlUICommand x:Key="EdiCommand" Command="{x:Bind ViewModel.EditUserCommand}" />

 <!--  List view swipeviews items?  -->
 <FontIconSource x:Key="ViewIcon" Glyph="&#xE890;" />
 <FontIconSource x:Key="EditIcon" Glyph="&#xE932;" />
 <FontIconSource x:Key="DeleteIcon" Glyph="&#xE74D;" />



        <DataTemplate x:Key="UserViewDesktop_Layout" x:DataType="ViewModels:UsersViewModel">
            <Grid ColumnSpacing="10" RowSpacing="10">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="auto" MinWidth="160" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="auto" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="*" />
                    <RowDefinition Height="auto" />
                </Grid.RowDefinitions>



                <ComboBox
                    Grid.Row="0"
                    Grid.Column="0"
                    Grid.ColumnSpan="2"
                    MinWidth="150"
                    VerticalAlignment="Center"
                    Header="Search by:"
                    SelectedIndex="1">
                    <ComboBox.Items>
                        <x:String>ID</x:String>
                        <x:String>Name</x:String>
                        <x:String>Phone</x:String>
                    </ComboBox.Items>
                </ComboBox>


                <AutoSuggestBox
                    Grid.Row="0"
                    Grid.Column="1"
                    VerticalAlignment="Center"
                    Header="Search"
                    PlaceholderText="Search users"
                    QueryIcon="Find" />

                <AppBarButton
                    Grid.Row="0"
                    Grid.Column="2"
                    Margin="0,10,0,0"
                    VerticalAlignment="Center"
                    Command="{Binding CreateUserCommand}"
                    Icon="Add"
                    Label="Add" />


                <ListView
                    x:Name="lst"
                    Grid.Row="1"
                    Grid.Column="0"
                    Grid.ColumnSpan="3"
                    MinHeight="710"
                    Margin="10"
                    Header="Users List"
                    ItemsSource="{Binding AppUsers, Mode=TwoWay}"
                    SelectedItem="{Binding SelectedUser, Mode=TwoWay}"
                    SelectionMode="Single">

                    <ListView.ItemTemplate>
                        <DataTemplate x:Name="dskListView" x:DataType="coreModels:Users">
                            <SwipeControl
                                x:Name="userswipte"
                                Height="48"
                                HorizontalContentAlignment="Stretch"
                                BorderBrush="{ThemeResource ButtonBackground}"
                                BorderThickness="0,1,0,0"
                                ContextFlyout="{StaticResource ListViewMenu}"
                                CornerRadius="10"
                                RightItems="{StaticResource right}">

                                <SwipeControl.LeftItems>
                                    <SwipeItems Mode="Reveal">
                                        <SwipeItem
                                            Background="{ThemeResource SystemFillColorSuccessBrush}"
                                            IconSource="{StaticResource ViewIcon}"
                                            Text="View" />
                                        <SwipeItem
                                            x:DefaultBindMode="TwoWay"
                                            Background="{ThemeResource SystemFillColorAttentionBrush}"
                                            Command="{StaticResource EdiCommand}"
                                            CommandParameter="{Binding ElementName=userswipte, Path=DataContext}"
                                            IconSource="{StaticResource EditIcon}"
                                            Text="Edit" />
                                    </SwipeItems>
                                </SwipeControl.LeftItems>

                                <Grid Margin="10,0">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="auto" />
                                        <ColumnDefinition Width="1*" />
                                        <ColumnDefinition Width="1*" />
                                        <ColumnDefinition Width="1*" />
                                        <ColumnDefinition Width="auto" />
                                    </Grid.ColumnDefinitions>

                                    <TextBlock
                                        Grid.Column="0"
                                        Margin="10,2"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Center"
                                        Text="{Binding Id}" />

                                    <TextBlock
                                        Grid.Column="1"
                                        Margin="12"
                                        HorizontalAlignment="Stretch"
                                        VerticalAlignment="Center"
                                        FontSize="18"
                                        Text="{Binding FullName}" />

                                    <TextBlock
                                        Grid.Column="2"
                                        Margin="0,0,10,0"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Center"
                                        Text="{Binding Role}" />

                                    <TextBlock
                                        Grid.Column="3"
                                        Margin="0,0,10,0"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Center"
                                        Text="{Binding MobileNumber}" />

                                    <TextBlock
                                        Grid.Column="4"
                                        Margin="0,0,10,0"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Center"
                                        Text="{Binding Username}" />


                                </Grid>
                            </SwipeControl>
                        </DataTemplate>
                    </ListView.ItemTemplate>

                </ListView>
 
        </DataTemplate>
 </Page.Resources>

<ContentControl
    x:Name="ResponsiveContent" 
    Content="{x:Bind ViewModel}"
    ContentTemplate="{StaticResource UserViewDesktop_Layout}"/>
</Page>

Viewmodel.cs


using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using _yourproject.Contracts.Services;
using _yourproject.Core.Models; 

namespace _yourproject.ViewModels;

public partial class UsersViewModel : ObservableRecipient
{
    public INavigationService _navigationService;


    [ObservableProperty]
    public partial string TotalUsers { set; get; }


    [ObservableProperty]
    public partial ObservableCollection<Users> AppUsers { set; get; }

    [ObservableProperty]
    public partial Users SelectedUser { set; get; }


// this command I want to bind to the listview datatemplate? 

    [RelayCommand]
    void EditUser(Users usr)
    {
        if (usr != null)
            _navigationService.NavigateTo(typeof(UserEditViewModel).FullName?? "UserEditViewModel", usr);
    }
} 

Model:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using _yourproject.Core.Models.Facelatators;

namespace _yourproject.Core.Models
{
    public class Users
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public long Id { get; set; }

        [Required(ErrorMessage = "Full name is required.")] // Ensures the field is mandatory
        [StringLength(200, MinimumLength = 4, ErrorMessage = "Full name must be between 4 and 200 characters.")]
        [RegularExpression(@"^[a-zA-Z\s]+$", ErrorMessage = "Full name must only contain letters and spaces.")]
        public string? FullName { get; set; }

        [MinLength(4, ErrorMessage ="Minimum of 4 charcters.")]
        public string? Username { get; set; }
        [Phone(ErrorMessage ="Mobile is requied!.")]
        public string? MobileNumber { get; set; }

        [Required(ErrorMessage = "Password is Reauired!.")]
        public string Password { get; set; }

// this is an enum
        public Role Role { get; set; } = Role.User;
        public DateTime? HiredDate { get; set; } = DateTime.Now;

    }
}

in this code the context menu working properly but the swipe item binding is not working. so, how to bind the swipe control item to command in viewmodel and bind the current items as the command parameter?

any one could help me?


Solution

  • I created a test app based on the code you shared but it doesn't seem to be working. This might be related to this issue.

    I suggest you using the Invoked event.

    <SwipeItem
        Background="{ThemeResource SystemFillColorAttentionBrush}"
        IconSource="{StaticResource EditIcon}"
        Invoked="EditSwipeItem_Invoked"
        Text="Edit" />
    
    private void EditSwipeItem_Invoked(SwipeItem sender, SwipeItemInvokedEventArgs args)
    {
        ViewModel.EditUserCommand.Execute(args.SwipeControl.DataContext);
    }