C# 在ViewModel中访问Xamarin.Forms

C# 在ViewModel中访问Xamarin.Forms,c#,xamarin,mvvm,xamarin.forms,C#,Xamarin,Mvvm,Xamarin.forms,我对Xamarin.forms中的跨平台开发非常陌生。我的代码应该是高度可单元测试的,我已经创建了一个ViewModel类来在我的视图和模型之间进行通信。我想知道,如果我们要访问viewmodel中的Xamarin.forms(使用Xamarin.forms;),这是一种不好的做法还是违反了MVVM的概念。如果是这样,我们如何在ViewModel中使用命令绑定视图 谢谢从视图模型访问视图确实“违背”了MVVM原则。你说得对!绑定一个命令,并不是那么难,它的工作原理与您可能使用的任何其他绑定一样

我对Xamarin.forms中的跨平台开发非常陌生。我的代码应该是高度可单元测试的,我已经创建了一个
ViewModel
类来在我的
视图
模型
之间进行通信。我想知道,如果我们要访问viewmodel中的Xamarin.forms(使用Xamarin.forms;),这是一种不好的做法还是违反了MVVM的概念。如果是这样,我们如何在ViewModel中使用命令绑定视图


谢谢

从视图模型访问视图确实“违背”了MVVM原则。你说得对!绑定一个
命令
,并不是那么难,它的工作原理与您可能使用的任何其他绑定一样

在视图模型中,只需为
命令定义一个属性即可:

public class YourViewModel
{
    public Command YourCommand { get; set; }
}
然后在构造函数中定义应执行的逻辑:

public YourViewModel()
{
    YourCommand = new Command(() =>
    {
        Console.WriteLine("TADA!");
    });
}
当然,您可以将它定义为它自己的单独方法,或者以另一种方式声明它。为了简单起见,我现在已经在线完成了

要从XAML绑定到它,只需执行以下操作:

<Button Text="Make it so!" Command="{Binding YourCommand}" />

并确保已将页面上的
BindingContext
属性设置为视图模型。如果您使用的是MVVM框架,那么您可能已经这样做了


在某些情况下,您可能希望绑定到
列表视图中的单元格或类似的单元格。在这种情况下,请记住范围会发生变化。然后绑定到该单元格后面的视图模型,而不是页面。因此,您必须引用该页面才能访问该
BindingContext
。但是,当你到达那里时,请记住它有一些特殊之处。

从视图模型访问视图确实“违反”了MVVM原则。你说得对!绑定一个
命令
,并不是那么难,它的工作原理与您可能使用的任何其他绑定一样

在视图模型中,只需为
命令定义一个属性即可:

public class YourViewModel
{
    public Command YourCommand { get; set; }
}
然后在构造函数中定义应执行的逻辑:

public YourViewModel()
{
    YourCommand = new Command(() =>
    {
        Console.WriteLine("TADA!");
    });
}
当然,您可以将它定义为它自己的单独方法,或者以另一种方式声明它。为了简单起见,我现在已经在线完成了

要从XAML绑定到它,只需执行以下操作:

<Button Text="Make it so!" Command="{Binding YourCommand}" />

并确保已将页面上的
BindingContext
属性设置为视图模型。如果您使用的是MVVM框架,那么您可能已经这样做了


在某些情况下,您可能希望绑定到
列表视图中的单元格或类似的单元格。在这种情况下,请记住范围会发生变化。然后绑定到该单元格后面的视图模型,而不是页面。因此,您必须引用该页面才能访问该
BindingContext
。但是,当您到达那里时,请记住它有一些特殊之处。

使用以下代码,因此您不需要导入Xamarin。ViewModel中的表单:

按钮行为

 public class ButtonBehavior : Behavior<Button>
    {
        protected override void OnAttachedTo(Button bindable)
        {
            base.OnAttachedTo(bindable);
            bindable.Clicked += Bindable_Clicked;
        }

        private void Bindable_Clicked(object sender, EventArgs e)
        {
            //Use you logic here
        }

        protected override void OnDetachingFrom(Button bindable)
        {
            base.OnDetachingFrom(bindable);
            bindable.Clicked -= Bindable_Clicked;
        }
    }
公共类按钮行为:行为
{
受保护的超控无效附加DTO(按钮可绑定)
{
碱。可粘合的DTO(可粘合);
bindable.Clicked+=bindable\u Clicked;
}
已单击私有void Bindable_(对象发送方,事件参数e)
{
//用你的逻辑
}
受保护的覆盖无效OnDetachingFrom(按钮可绑定)
{
基础。从(可装订)开始连接;
bindable.Clicked-=bindable\u Clicked;
}
}
查看

    <Button Text="Click Me" HeightRequest="50" WidthRequest="80">
        <Button.Behaviors>
            <behavior:ButtonBehavior/>
        </Button.Behaviors>
    </Button>

使用以下代码,因此您无需在ViewModel中导入Xamarin.Forms:

按钮行为

 public class ButtonBehavior : Behavior<Button>
    {
        protected override void OnAttachedTo(Button bindable)
        {
            base.OnAttachedTo(bindable);
            bindable.Clicked += Bindable_Clicked;
        }

        private void Bindable_Clicked(object sender, EventArgs e)
        {
            //Use you logic here
        }

        protected override void OnDetachingFrom(Button bindable)
        {
            base.OnDetachingFrom(bindable);
            bindable.Clicked -= Bindable_Clicked;
        }
    }
公共类按钮行为:行为
{
受保护的超控无效附加DTO(按钮可绑定)
{
碱。可粘合的DTO(可粘合);
bindable.Clicked+=bindable\u Clicked;
}
已单击私有void Bindable_(对象发送方,事件参数e)
{
//用你的逻辑
}
受保护的覆盖无效OnDetachingFrom(按钮可绑定)
{
基础。从(可装订)开始连接;
bindable.Clicked-=bindable\u Clicked;
}
}
查看

    <Button Text="Click Me" HeightRequest="50" WidthRequest="80">
        <Button.Behaviors>
            <behavior:ButtonBehavior/>
        </Button.Behaviors>
    </Button>


为了访问命令,我们需要将Xamarin.Forms导入到我们的ViewModel中。我想知道这是违法的吗?因为我听说我们不应该将Xamarin.Forms导入我们的ViewModelAh,这就是您的意思。如果它真的困扰你,你可以选择
ICommand
。但是引用Xamarin.Forms并没有那么糟糕。只要你不从视图模型引用你的视图。如果我尝试像这样使用ICommand,ConvertToGeoCodeCommand=newICommand(ConvertToGeoCode);“无法创建抽象类或接口‘ICommand’的实例”ICommand是一个接口,不能直接创建接口。但是您可以将它定义为一个接口,因此它将是:
public ICommand YourCommand{get;set;}
但是,如果您确实不想引用Xamarin.Forms,那么您将需要某种工厂模式,因为在执行
YourCommand=new Command(…)
时,您仍然需要引用。如果我是你,我现在会使用常规命令,当你开始掌握它的诀窍并且仍然想摆脱引用时,在学习了基础知识之后,看看如何做到这一点。为了使用acces命令,我们需要将Xamarin.Forms导入到我们的ViewModel中。我想知道这是违法的吗?因为我听说我们不应该将Xamarin.Forms导入我们的ViewModelAh,这就是您的意思。如果它真的困扰你,你可以选择
ICommand
。但是引用Xamarin.Forms并没有那么糟糕。只要你不从视图模型引用你的视图。如果我尝试像这样使用ICommand,ConvertToGeoCodeCommand=newICommand(ConvertToGeoCode);“无法创建实例