首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WinUI 3从DataTemplate绑定到父ViewModel

WinUI 3从DataTemplate绑定到父ViewModel
EN

Stack Overflow用户
提问于 2022-10-14 10:10:11
回答 2查看 65关注 0票数 0

在WinUI 3应用程序中,使用CommunityToolkit.Mvvm,我有一个XXXPage,它有一个ListDetailsView。

我为ListDetailsView DetailsTemplate定义了一个DetailsTemplate,其中包含一个用户控件: XXXDetailControl。

我试图将XXXDetailControl的XXXDetailControl事件绑定到页面的ViewModel InstallCommand,但没有成功。

代码语言:javascript
运行
复制
<DataTemplate x:Key="DetailsTemplate">
    <Grid>
        <views:XXXDetailControl 
            DetailMenuItem="{Binding}"                   
            InstallClicked="{ ????  }" />
   </Grid>
        ...
</DataTemplate>

如何设置此绑定,以便将DataTemplate中定义的控件中的事件绑定到页面视图模型命令?如何设置此绑定,以便与事件一起发送选定的项?

XXXPage.xaml :

代码语言:javascript
运行
复制
    <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>

XXXPage.cs :

代码语言:javascript
运行
复制
public sealed partial class XXXPage: Page
{
    public XXXViewModel ViewModel
    {
        get;
    }

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

the XXXViewModel :

代码语言:javascript
运行
复制
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;
}
EN

回答 2

Stack Overflow用户

发布于 2022-10-14 12:52:00

如果您可以在用户控件中使用CommandCommandParameter,则可以这样做。

DetailsControl.xaml.cs

代码语言:javascript
运行
复制
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);
    }
}

DetailsControl.xaml

代码语言:javascript
运行
复制
<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>

MainPageViewModel.cs

代码语言:javascript
运行
复制
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" },
    };
}

MainPage.xaml.cs

代码语言:javascript
运行
复制
using Microsoft.UI.Xaml.Controls;

namespace CustomControlEvent;

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

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

MainPage.xaml

此页面名为“DataTemplate. ThisPage”,以便从

代码语言:javascript
运行
复制
<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>
票数 0
EN

Stack Overflow用户

发布于 2022-10-19 12:27:39

你试过像这样给Page一个Name吗?

代码语言:javascript
运行
复制
<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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74067709

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档