【问题标题】:How to provide Command-Property for custom control in MVVM (.NET MAUI)如何在 MVVM (.NET MAUI) 中为自定义控件提供命令属性
【发布时间】:2022-12-12 04:24:50
【问题描述】:

我正在尝试在 .NET MAUI 中构建自定义控件,它应该为其父级提供 ICommand 的 BindableProperty。这是我尝试实现的基本示例。

主页视图 (MainPage.xaml)

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:views="clr-namespace:SampleApp.Views"
             x:Class="SampleApp.MainPage">

    <views:MyCustomControl DoSomething="{Binding DoSomethingCommand}"></views:MyCustomControl>
</ContentPage>

MainPage 视图类 (MainPage.xaml.cs)

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        BindingContext = new MainPageViewModel();
    }
}

主页视图模型 (MainPage ViewModel.cs)

public class MainPageViewModel : ObservableObject
{
    public ICommand ProcessNewScoreCommand { get; }

    public MainPageViewModel()
    {
        ProcessNewScoreCommand = new Command(DoSomething);
    }

    private void DoSomething()
    {
        // Do something
    }
}

MyCustomControl 视图类 (MyCustomControl.xaml.cs)

public partial class MyCustomControl : ContentView
{
    public static readonly BindableProperty DoSomethingProperty =
        BindableProperty.Create(nameof(DoSomething), typeof(ICommand), typeof(MyCustomControl));

    public ICommand DoSomething
    {
        get => (ICommand)GetValue(DoSomethingProperty);
        set => SetValue(DoSomethingProperty, value);
    }

    public MyCustomControl()
    {
        InitializeComponent();
        BindingContext = new MyCustomControlViewModel(DoSomething);
    }
}

MyCustomControl 视图模型 (MyCustomControlViewModel.cs)

public class MyCustomControlViewModel : ObservableObject
{
    public ICommand DoSomething { get; }

    public MyCustomControlViewModel(ICommand doSomethingCommand)
    {
        DoSomething = doSomethingCommand;
    }

    private void PerformSomeLogic()
    {
        // Any calulations/logic
        // ...

        if (DoSomething.CanExecute(null))
        {
            // Execute command, so that parent component gets informed and can act.
            DoSomething.Execute(null);
        }
    }
}

调试时,类MyCustomControl.xaml.cs 的属性DoSomething 始终为空。而且,它的设置器似乎在任何时候都不会被调用。我究竟做错了什么?

【问题讨论】:

    标签: c# .net mvvm maui


    【解决方案1】:

    它不起作用的原因是您正在为您的自定义控件创建一个 VM,即视图然后为其分配上下文,然后在您的自定义控件中您再次更改其 BindingContext,自定义控件不应该有自己的预定义 BindingContext .

    解决此问题的步骤:

    • 删除你的MyCustomControlViewModel 类。

    • 现在你的 CustomControl.xaml.cs 看起来像这样:

      public partial class MyCustomControl : ContentView
      {
      
        public static readonly BindableProperty DoSomethingProperty =
                      BindableProperty.Create(nameof(DoSomething), typeof(ICommand), typeof(MyCustomControl));
      
        public ICommand DoSomething
        {
            get => (ICommand)GetValue(DoSomethingProperty);
            set => SetValue(DoSomethingProperty, value);
        }
      
        public MyCustomControl()
        {
            InitializeComponent();
        }
      }
      
    • 现在你的 Views VM 应该是处理逻辑的那个,这样你就不会有多个 BindingContext 混淆和编译器(通过在错误的地方搜索它):

      公共类 MainPageViewModel :ObservableObject {

        public ICommand DoSomething { get; }
      
       public MainPageViewModel()
       {
          DoSomething = new Command(DoSomething);
       }
      

    祝你好运,如果您还有其他问题,请告诉我。

    使用 XF 和 MAUI 的 MVVM 基本指南:https://learn.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/data-bindings-to-mvvm

    【讨论】:

    • 感谢您的回复。这是否意味着我的自定义控件根本不应接收 ViewModel?我对 MVVM 很陌生,但这听起来我根本不会有任何分离。我想为自定义控件定义的属性与 MainPage 无关,仅用于控件的可视化。我想使用问题中提到的命令向 MainPage 报告控件基于某些用户输入计算出的值。我也不明白,MainPage 的有界命令是如何从自定义控件触发的(没有自己的视图模型)。
    • 在这种情况下,您的自定义控件是应该保存您的属性的地方,更像这样:github.com/trailheadtechnology/xf-custom-controls/blob/main/…,控件没有单独的 VM,您将有一个 VM 来处理所有视图后台逻辑
    • 感谢@FreakyAli,将使用代码隐藏按照链接中提到的那样进行操作。会将您的第一篇文章标记为答案,因为对我来说,总体信息应该是自定义控件没有自己的视图模型。只有一个。
    猜你喜欢
    • 2022-08-14
    • 1970-01-01
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 2011-12-17
    相关资源
    最近更新 更多