从任何地方更改控件

Changing Controls from anywhere

我想做的事情:

我想在我的代码中的任何位置更改按钮的背景颜色(其他 类 Xamarin Forms)。例如,页面 A 中的按钮 A 更改页面 B 中按钮 B 的颜色

在 Windows 上,您可以使用 MethodInvoker Delegat,但在 Android/iOS 上不可用。 你能给我一个提示吗?

我之前用 MVVM 方法尝试过使用按钮的文本。

在我的 PageB.xaml:

<Button Name="Button_B" Text="{Binding MyText}"/>

在我的 PageB.cs 在 public 页面 B

BindingContext = new MVVMPageB();

在我的 MVVM 中PageB.cs

private string myText;
public string MyText
{ 
get => mytring;
set
{
mystring = value;
PropertyChanged?
.Invoke(this, new PropertyChangedEventArgs(MyText)));
}

如果我打电话:

MyText("Test");

在我的 MVVMPageB.cs 中它工作正常。但我不知道如何从其他任何地方访问它。 我试过了:

var Testobjekt = new MVVMPageB() //pretty sure thats not correct
Testobjekt.MyText("Test"); //wont work

技术 1

这是 MVVMPageB 的单例模式。

如果您从来没有两个“页面 B”,这将有效。 IF 导航堆栈上有一个页面 B(因此您可以“返回”到它),然后显示另一个页面 B,THEN这不会很好地工作,因为两个页面 B 都将引用相同的 MVVMPageB 实例。

public class MVVMPageB : ...
{
    // "Singleton": This is the only instance of MVVMPageB.
    private static MVVMPageB _It;
    public static MVVMPageB It
    {
        if (_It == null)
            _It = new MVVMPageB();
        return _It;
    }

    // Your constructor.
    // It is private; only used via "It" getter above.
    private MVVMPageB()
    {
        ...
    }
}

另一个class中的代码,用于访问MVVMPageB的成员。

MVVMPageB.It.MyText("Test");

替换此代码:

BindingContext = new MVVMPageB();

使用此代码:

BindingContext = MVVMPageB.It;

注意:因为 MVVMPageB.It 是静态的,如果您第二次访问页面 B,它将显示您上次(在同一个应用程序会话中)的值。


技巧二

一种更稳健的方法,即使您创建另一个页面 B 也能工作,需要有某种方法将 MVVMPageB 的当前实例传递给 MVVMPageA 或 PageA。

一个完整的示例完全取决于 how/where 您创建的每个页面。但这表明了这个想法。

public class MVVMPageB : ...
{
    // Your constructor. Add parameters as needed.
    public MVVMPageB()
    {
        ...
    }
}

public partial class PageB : ...
{
    // Convenience property - our BindingContext is type MVVMPageB.
    public MVVMPageB VMb => (MVVMPageB)BindingContext;
    ...
}

public class MVVMPageA : ...
{
    // This is here, so both MVVMPageA and PageA can find it.
    public MVVMPageB VMb;
}

public partial class PageA : ...
{
    // Convenience property - our BindingContext is type MVVMPageA.
    public MVVMPageA VMa => (MVVMPageA)BindingContext;
    ...
}
    

创建页面 B 和页面 A 的代码:

var pageB = new PageB();
var pageA = new PageA();
// Tell MVVMPageA about MVVMPageB.
pageA.VMa.VMb = pageB.VMb;

MVVMPageA 中的方法现在可以访问 MVVMPageB 的成员:

VMb.MyText("Test");

PageA 中的方法现在可以访问 MVVMPageB 的成员:

VMa.VMb.MyText("Test");

注意:在这种动态技术中,如果您第二次访问页面 B(在同一个应用程序会话中),它将有一个新的 MVVMPageB 实例。

您需要一个单独的 viewModel 才能使用。我通常将一个用于导航栏。
所以每个作用域页面 viewModel 都引用里面的单例全局 viewModel:

PageAViewModel 有 属性NavBarModel
PageBViewModel 有 属性 NavBarModel
等等..

所以很明显你的按钮将被绑定为 BackgroundColor={Binding NavBarModel.ActionColor} 在每个不同的页面上。
现在要有一个单例并获取它的引用,我可以看到两种方法:依赖注入 (DI) 或创建单实例。您可以在网上阅读很多关于 DI 的信息,而对于一个简单的案例,您可以拥有一个带有 prop 的单实例模型:

private NavBarModel _current;
public NavBarModel Current
{
    get
    {
        if (_current == null)
            _current = new NavBarModel();
        return _current;
    }
}

然后在页面 viewModels 构造函数中设置 NavBarModel = NavBarModel.Current;

尽管您需要 DI 以在单例中引用更多模型,or/and 使您的代码更可重用。祝你好运。