XAML 从DataTemplate到父ViewModel的WinUI 3绑定

ccgok5k5  于 2022-12-07  发布在  其他
关注(0)|答案(2)|浏览(196)

在一个WinUI 3应用程序中,使用CommunityToolkit.mvvm,我有一个 XXXPage,它有一个 ListDetailsView
我为ListDetailsView DetailsTemplate定义了一个DateTemplate,其中包含一个用户控件:* XXX详细控制 *。
我尝试将XXXDetailControl的InstallClicked事件绑定到页面的ViewModel InstallCommand,但没有成功。

<DataTemplate x:Key="DetailsTemplate">
    <Grid>
        <views:XXXDetailControl 
            DetailMenuItem="{Binding}"                   
            InstallClicked="{ ????  }" />
   </Grid>
        ...
</DataTemplate>

如何设置此绑定,以便将DataTemplate中定义的控件的事件绑定到page viewmodel命令?如何设置此绑定,以便将选定项与事件一起发送?

XXX第.xaml页:

<Page
    x:Class="XXXPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:models="using:XXX.Models"
    xmlns:views="using:XXX.Views"
    xmlns:behaviors="using:XXX.Behaviors" 
    xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls"
    xmlns:viewmodels="using:XXX.ViewModels"
    behaviors:NavigationViewHeaderBehavior.HeaderMode="Never"    
    mc:Ignorable="d">
    <Page.Resources>
        ...
        <DataTemplate x:Key="DetailsTemplate">
            <Grid>
                <views:XXXDetailControl 
                    DetailMenuItem="{Binding}"                   
                    InstallClicked="{Binding ViewModel.InstallCommand, ElementName=?}" CommandParameter="{x:Bind (viewmodels:XXXDetailViewModel)}" />
            </Grid>
        ...
        </DataTemplate>
    </Page.Resources>

    <Grid x:Name="ContentArea">
    ...
        <controls:ListDetailsView
            x:Uid="ListDetails"
            x:Name="ListDetailsViewControl"
            DetailsTemplate="{StaticResource DetailsTemplate}"
            ItemsSource="{x:Bind ViewModel.Items}"/>

    </Grid>
    </Page>

XXX第.cs页:

public sealed partial class XXXPage: Page
{
    public XXXViewModel ViewModel
    {
        get;
    }

    public XXXPage()
    {
        ViewModel = App.GetService<XXXViewModel >();
        InitializeComponent();
    }
}

XXX视图模型:

public class XXXViewModel : ObservableRecipient, INavigationAware
{
       private XXXDetailViewModel? _selected;
    public XXXDetailViewModel? Selected
    {
        get => _selected;
        set
        {
            SetProperty(ref _selected, value);
        }
    }
    public ObservableCollection<XXXDetailViewModel> Items { get; private set; } = new ObservableCollection<XXXDetailViewModel>();

    public ICommand InstallCommand;
}
yqyhoc1h

yqyhoc1h1#

如果您可以在使用者控件内使用CommandCommandParameter,就可以这样做。

详细信息控件. xaml.cs

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Windows.Input;

namespace CustomControlEvent;

public sealed partial class DetailControl : UserControl
{
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        nameof(Text),
        typeof(string),
        typeof(DetailControl),
        new PropertyMetadata(default));

    public static readonly DependencyProperty ClickCommandProperty = DependencyProperty.Register(
        nameof(ClickCommand),
        typeof(ICommand),
        typeof(DetailControl),
        new PropertyMetadata(default));

    public static readonly DependencyProperty ClickCommandParameterProperty = DependencyProperty.Register(
        nameof(ClickCommandParameter),
        typeof(object),
        typeof(DetailControl),
        new PropertyMetadata(default));

    public DetailControl()
    {
        this.InitializeComponent();
    }

    public object ClickCommandParameter
    {
        get => (object)GetValue(ClickCommandParameterProperty);
        set => SetValue(ClickCommandParameterProperty, value);
    }

    public string Text
    {
        get => (string)GetValue(TextProperty);
        set => SetValue(TextProperty, value);
    }

    public ICommand ClickCommand
    {
        get => (ICommand)GetValue(ClickCommandProperty);
        set => SetValue(ClickCommandProperty, value);
    }
}

详细信息控件.xaml

<UserControl
    x:Class="CustomControlEvent.DetailControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:CustomControlEvent"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid>
        <Button
            Command="{x:Bind ClickCommand, Mode=OneWay}"
            CommandParameter="{x:Bind ClickCommandParameter, Mode=OneWay}"
            Content="{x:Bind Text, Mode=OneWay}" />
    </Grid>
</UserControl>

主页面视图模型.cs

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;

namespace CustomControlEvent;

public partial class MainPageViewModel : ObservableObject
{
    [RelayCommand]
    private void Run(object commandParameter)
    {
    }

    [ObservableProperty]
    private ObservableCollection<DetailsViewModel> items = new()
    {
        new DetailsViewModel() { Details = "A" },
        new DetailsViewModel() { Details = "B" },
        new DetailsViewModel() { Details = "C" },
    };
}

主页面.xaml.cs

using Microsoft.UI.Xaml.Controls;

namespace CustomControlEvent;

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
    }

    public MainPageViewModel ViewModel { get; } = new();
}

主页面.xaml

此页被命名为ThisPage,以便从DataTemplate绑定。

<Page
    x:Class="CustomControlEvent.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:CustomControlEvent"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    x:Name="ThisPage"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    mc:Ignorable="d">

    <StackPanel>
        <StackPanel.Resources>
            <DataTemplate
                x:Key="DetailsTemplate"
                x:DataType="local:DetailsViewModel">
                <Grid>
                    <local:DetailControl
                        ClickCommand="{Binding ElementName=ThisPage, Path=ViewModel.RunCommand}"
                        ClickCommandParameter="{x:Bind}"
                        Text="{x:Bind Details, Mode=OneWay}" />
                </Grid>
            </DataTemplate>
        </StackPanel.Resources>

        <ListView
            ItemTemplate="{StaticResource DetailsTemplate}"
            ItemsSource="{x:Bind ViewModel.Items, Mode=OneWay}" />

    </StackPanel>

</Page>
nukf8bse

nukf8bse2#

你有没有试着给予Page一个这样的Name?:

<Page ...
    Name="thePage">
    <Page.Resources>
        ...
        <DataTemplate x:Key="DetailsTemplate">
            <Grid>
                <views:XXXDetailControl 
                    DetailMenuItem="{Binding}"                   
                    InstallClicked="{Binding ViewModel.InstallCommand, ElementName=thePage}" ... />
            </Grid>
        ...
        </DataTemplate>
    </Page.Resources>

这似乎适用于ListView

相关问题