【问题标题】:best practice to pass parameters between open pages在打开的页面之间传递参数的最佳实践
【发布时间】:2019-01-06 16:16:23
【问题描述】:

我正在开发一个有两个页面的 Windows 应用程序 (UWP),我想要在页面之间传递参数的最佳实践。

这是我的场景:

我们有两个页面,每个页面都打开并保持在屏幕中间,每个页面上都有一个按钮,当我们点击它时,它会将消息发送到另一个页面。

我也想不断重复地传递信息。

在 Page1.cs 中:

     Page2 page2;
         public Page1()
                {
                    this.InitializeComponent();         
                    CreatPage2();
                }

         // creat page 2
           private async void CreatPage2()
                {
                    var NewWindow = CoreApplication.CreateNewView();
                    int NewWindowid = 0;

                    await NewWindow.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
                    {
                        Frame newframe = new Frame();
                        newframe.Navigate(typeof(Page2), this);
                        Window.Current.Content = newframe;
                        Window.Current.Activate();
                        ApplicationView.GetForCurrentView().Title = "page2";
                        NewWindowid = ApplicationView.GetForCurrentView().Id;
                    });

                    await Windows.UI.ViewManagement.ApplicationViewSwitcher.TryShowAsStandaloneAsync(NewWindowid);
                }

                //Button


     private void ChangeP2_Click(object sender, RoutedEventArgs e)
                {
                  // send a message to the texblock in the page2
        page2.TexBlock2.Text=$"From page1 :{e.ToString()}";
// change  text color of the texblock in the page2
page2.Foreground= new SolidColorBrush(Windows.UI.Colors.Red);
                }

在 Page2.cs 中:

  Page1 page1;
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        page1 = e.Parameter as Page1;
        base.OnNavigatedTo(e);
    }

    public Page2()
    {
        this.InitializeComponent();         
    }



    //Button
     private void ChangeP1_Click(object sender, RoutedEventArgs e)
    {
// send a message to the texblock in the page1
      page1.TexBlock1.Text=$"From page2 :{e.ToString()}";
// change  text color of the texblock in the page1
page1.Foreground= new SolidColorBrush(Windows.UI.Colors.Red);
    }

上面的代码只适用于 page2 到 page1。 (它可以改变pagea的文本块)。 请帮助我,我找不到适用于两页的解决方案

【问题讨论】:

  • 你尝试过简单的事件吗?
  • 不,如果你知道请帮助我。

标签: c# xaml uwp


【解决方案1】:

不……最好的方法是使用由应用 ViewModel 类组成的标准模式,该类包含您要在逻辑层中使用的所有常见应用数据。

我总是这样:

1) 我使用自动创建的 MainPage 作为应用程序的“外壳”,其属性为AppViewModel。 MainPage(以及AppViewModel)可以从应用程序的任何地方访问,方法是将其自身设置为自己的类中的静态字段。

这是代码,比你想象的要简单:

public sealed partial class MainPage : Page
{
    public AppViewModel ViewModel { get; set; } = new AppViewModel();
    public static MainPage Current { get; set; }

    public MainPage()
    {
        this.InitializeComponent();
        Current = this;
    }
}

2) AppViewModel 本身是一个必须实现INotifyPropertyChanged 接口的类,以启用可绑定的属性和功能。 开发人员通常会创建一个实现它的基类,然后从中派生所有需要可绑定属性的类。

这里是:

public class BaseBind : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged([CallerMemberName] string propertyName = null) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    protected bool SetProperty<T>(ref T storage, T value,
        [CallerMemberName] String propertyName = null)
    {
        if (object.Equals(storage, value)) return false;
        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

然后你从它派生AppViewModel 类(以及所有其他模型和视图模型类)......用你需要跨页面共享的所有公共属性填充它。 我什至添加了一个派生属性,以展示如何一次共享多个数据类型,以及一个函数:

public class AppViewModel : BaseBind
{
    public AppViewModel()
    {
        // ...
    }

    // All common app data
    private string sampleCommonString;
    public String SampleCommonString
    {
        get { return sampleCommonString; }
        set { SetProperty(ref sampleCommonString, value); OnPropertyChanged(nameof(SampleDerivedProperty1)); OnPropertyChanged(nameof(SampleDerivedProperty2)); }
    }

    public String SampleDerivedProperty1 =>  "return something based on SampleCommonString";

    public String SampleDerivedProperty2
    {
        get
        {
            <<evaluate SampleCommonString>>
            return "Same thing as SampleDerivedProperty1, but more explicit";
        }
    }

    // This is a property that you can use for functions and internal logic… but it CAN'T be binded
    public String SampleNOTBindableProperty { get; set; }

    public void SampleFunction()
    {
        // Insert code here.

        // The function has to be with NO parameters, in order to work with simple {x:Bind} markup.
        // If your function has to access some specific data, you can create a new bindable (or non) property, just as the ones above, and memorize the data there.
    }
}

3) 然后,为了从另一个 Page 访问所有这些,只需在该页面中创建一个 AppViewModel 字段,如下所示:

public sealed partial class SecondPage : Page
{
    public AppViewModel ViewModel => MainPage.Current.ViewModel;

    public SecondPage()
    {
        this.InitializeComponent();
    }
}

...您可以轻松地将 XAML 控件属性绑定到 AppViewModel 本身:

<TextBlock Text="{x:Bind ViewModel.SampleCommonString, Mode=OneWay}"/>
<Button Content="Sample content" Click="{x:Bind ViewModel.SampleFunction}"/>

(Mode=OneWay 用于实时绑定,以便即使在 UI 中也能立即更新属性,而Mode=TwoWay 用于那些可以从控件本身编辑的属性,由用户在为了与应用逻辑进行交互)。

希望这会有所帮助。

最好的问候和新年快乐。

【讨论】:

  • 是否适用于 Xamarin 平台?我的项目是 windows 应用程序。
  • 当然。我的回答特别适合 UWP 应用程序,但是(稍作改动)它也适用于 Xamarin 项目;总体思路还是一样的,想。最好的问候
  • @Mayson 如果我的回答对您有帮助,您可以接受。
  • ,感谢您的帮助,我如何在 Windows 应用程序 (UWP) 中使用它?我无法在 UWP 中使用 ViewModel API。
  • @Mayson 你不需要使用任何额外的 API(除了 INotifyPropertyChenged 接口)......只需实现我写的代码。
猜你喜欢
  • 2011-03-13
  • 2023-03-30
  • 1970-01-01
  • 2016-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-10
相关资源
最近更新 更多