xamarin 从ViewModel调用视图的CodeBehind中的方法?

xtupzzrd  于 2022-12-28  发布在  其他
关注(0)|答案(6)|浏览(132)

我在视图后面的代码中有一个方法(这个方法对我的UI做了一些事情)。
无论如何,我想从我的ViewModel中触发这个方法,怎么做呢?

siv3szwd

siv3szwd1#

我(也许还有其他人?)在MVVM方面的困难在于理解一件简单的事情:View知道ViewModel。我使用绑定和命令,但它们是简单的xaml中的strings。由于在运行时安全解析(安全意味着您可以输入错误,但软件不会崩溃),这使得视图与视图模型 * 解耦 *(至少在编译时)。我一直在寻找保持这种解耦的解决方案,例如,行为。
事实上,您可以直接访问视图模型,它通常是一个DataContext窗口/用户控件:

var vm = (MyViewModel)this.DataContext;

知道了这一点,使用事件可能是从视图模型调用视图方法的最佳方式,因为视图模型不知道是否有订阅者,它只是触发该事件,而事件可以被视图或其他视图模型使用。

// define in the view model
public delegate void MyEventAction(string someParameter, ...);
public event MyEventAction MyEvent;

// rise event when you need to
MyEvent?.Invoke("123", ...);

// in the view
var vm = (MyViewModel)DataContext;
vm.MyEvent += (someParameter, ...) => ... // do something
wdebmtf2

wdebmtf22#

您可以在View中这样做(代码隐藏)。
它强制转换为ViewModel要实现的接口,这样您就不会被限制为一个特定的ViewModel类型。

// CONSTRUCTOR
    public SomeView()
    {
        InitializeComponent();

        DataContextChanged += DataContextChangedHandler;
    }

    void DataContextChangedHandler(object sender, DependencyPropertyChangedEventArgs e)
    {
        var viewModel = e.NewValue as IInterfaceToBeImplementedByViewModel;

        if (viewModel != null)
        {
            viewModel.SomeEvent += (sender, args) => { someMethod(); }
        }
    }
gt0wga4j

gt0wga4j3#

根据x1e0 f1 a,ViewModel不知道View,因此这是不可接受的。要与ViewModel View交互,可能会触发命令,也可以使用绑定。此外,您不应将特定于UI的东西(如BusyIndicator)移动到ViewModel级别。
请提供更多关于您的具体用例的详细信息-当您想要调用视图的方法时,以及此方法的作用。

tuwxkamq

tuwxkamq4#

假设您在我的登录视图的代码背后有一个方法,如果登录失败,该方法通过将焦点带到密码条目来更新UI,那么从ViewModel触发此方法的最简单和最通用的方法是使用Action delegates
正如您在this sample中所看到的,在您的服务确定登录失败并且您希望Password Entry获得焦点的情况下,您所需要添加的全部内容是ViewModel中的两行代码和View中的一个操作处理程序。
视图模型代码:

  • 活动声明:public Action<bool> OnLoginFailed { get; set; }
  • 然后,在需要时,只需执行此OnLoginFailed?.Invoke(true);

查看代码:

ViewModel.OnLoginFailed = ((obj) =>
{
    PasswordEntry.Focus();
});

更新:I wrote an article以更详细地解释这一点

xn1cxnb4

xn1cxnb45#

我看到了你对上面答案的回复,你说你想让你的视图模型检索数据,然后告诉你的视图停止忙碌指示器。
我不确定我的解决方案是否是最好的解决方案,但你可以给予一下,也许有人可以纠正我的错误。
因此,从视图中,您可以调用ViewModel中的一个方法来开始阅读数据集,对吗?在这个方法中,您可以传递一个委托(指向视图中存在的一个方法),当ViewModel从服务器读取完数据集时,触发与视图中的方法相链接的委托(从视图模型中),该委托可以停止忙碌指示符。
所以在你看来

void StopBusyIndicator()
{
    this.BusyIndicator.IsBusy = false;
}

当你调用ViewModel来读取数据集时
这样称呼它:

ViewModel.ReadDataSet( ()= >StopBusyIndicator)

它将StopBusyIndicator方法作为委托传递,您可以在ReadDataSet的末尾调用该方法。
高温加热

camsedfj

camsedfj6#

您可以编写一个接受数据传输对象的操作类。在DTO中,添加一个名为“View”的属性,并将其分配给当前视图。通过视图代码隐藏中的控制器调用操作,取消DTO的装箱,现在您就可以完全控制操作类中的视图了。
如果你真的想在你的模型中这样做,只需在你的模型中创建一个带有“View”类型参数的方法,然后执行它,传入当前视图。

相关问题