我正在开发一个有两个页面的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);
}
Run Code Online (Sandbox Code Playgroud)
在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);
}
Run Code Online (Sandbox Code Playgroud)
上面的代码只适用于page2到page1.(它可以改变pagea的文本块).请帮助我,我找不到两页工作的解决方案
Naah ......最好的方法是使用由应用程序ViewModel类组成的标准模式,该类包含您要在逻辑层中使用的所有常见应用程序数据.
我总是这样做:
1)我使用自动创建的MainPage作为应用程序的"shell",其属性为AppViewModel.AppViewModel通过将自己设置为自己类中的静态字段,可以从应用程序中的任何位置访问MainPage(以及因此).
这是代码,比你想象的更简单:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后从中派生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.
}
}
Run Code Online (Sandbox Code Playgroud)
3)然后,为了从另一个访问所有这些Page,只需AppViewModel在该页面中创建一个字段,如下所示:
public sealed partial class SecondPage : Page
{
public AppViewModel ViewModel => MainPage.Current.ViewModel;
public SecondPage()
{
this.InitializeComponent();
}
}
Run Code Online (Sandbox Code Playgroud)
...并且您可以轻松地将XAML控件属性绑定到AppViewModel自身:
<TextBlock Text="{x:Bind ViewModel.SampleCommonString, Mode=OneWay}"/>
<Button Content="Sample content" Click="{x:Bind ViewModel.SampleFunction}"/>
Run Code Online (Sandbox Code Playgroud)
(Mode=OneWay用于实时绑定,以便即使在UI中也立即更新属性,同时Mode=TwoWay用于可以由控件本身由用户编辑的那些属性,以便与app逻辑交互).
希望这有帮助.
最好的问候和新年快乐.