Лучший и самый стандартный способ в C # / WPF / UWP - использовать стандартный шаблон, который состоит из общего класса ViewModel (который содержит все общие данные приложения, которые вы хотите использовать на уровне logi c). , вставьте как поле в stati c MainPage (или даже в класс App.xaml.cs).
Я всегда делаю это так:
1) Я использую автоматически созданную MainPage в качестве «оболочки» приложения со свойством AppViewModel
. К MainPage (и, следовательно, к AppViewModel
) можно получить доступ из любого места в приложении, задав себя как поле stati c в своем собственном классе (поле «Current» stati c может вызываться из любого места в приложении ... даже в классе MessageDialog!).
Это код для MainPage (или страницы оболочки, на которой вы sh, но я предлагаю сделать вот так, это довольно стандартный способ, используемый даже Microsoft), проще, чем вы думаете:
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;
}
}
ЭТО Уловка: сделать страницу stati c в одном поле в собственном классе, так что это поле stati c будет УНИКАЛЬНЫМ во всем приложении (это одна из основных особенностей слова «stati c») и, таким образом, позвонив по номеру MainPage.Current.ViewModel
, вы можете немедленно получить любые данные (в вашем конкретном случае c, StorageFile), хранящиеся там.
2) Сам AppViewModel
является классом который должен реализовывать интерфейс INotifyPropertyChanged
, чтобы включить привязываемые свойства и функции. Среди Windows разработчиков принято создавать базовый класс, реализующий его, а затем извлекать из него все классы, которым нужны связываемые (т. Е. Наблюдаемые) свойства.
Вот как именно Microsoft создает it:
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()
{
// Usually we initialize all the starting data here, in the viewmodel constructor...
}
// 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 in some way SampleCommonString...
return "Same thing as SampleDerivedProperty1, but it allows to add more than just one istruction";
}
}
// This is a property that you can use for functions and internal logic… but it CAN'T be binded to the UI directly
public String SampleNOTBindableProperty { get; set; }
public void SampleFunction()
{
// Insert code, that needs to interact with all the data contained in the viewmodel itself, 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
, ссылаясь на модель просмотра, содержащуюся на главной странице c:
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}"/>
<TextBox Text="{x:Bind ViewModel.SampleCommonString, Mode=TwoWay}"/>
<Button Content="Sample content" Click="{x:Bind ViewModel.SampleFunction}"/>
(Mode=OneWay
- для привязки в реальном времени, чтобы свойство немедленно обновлялось даже в пользовательском интерфейсе, а Mode=TwoWay
- для тех свойств, которые можно редактировать из c).
В этом режиме вы сможете отображать данные и все их изменения в реальном времени!
Итак ... это способ сохранить все данные приложения во время выполнения правильным и гибким способом ... изучая его и практикуясь, в будущем вы будете использовать этот шаблон даже более разумным способом, создавая модели просмотра для каждого obj ect вашего приложения (например: если ваше приложение должно хранить данные клиентов вашей компании, у вас будет класс «CustomerViewModel», производный от класса BaseBind, со всеми данными клиента в нем) и создание списков, например ObservableCollection<SampleViewModel>
для хранения всех из них (ObservableCollection<t>
- это тип коллекции, который имеет встроенный механизм для обработки изменений списка, таких как добавление, удаление и изменение порядка элементов списка). Затем вы свяжете каждую наблюдаемую коллекцию со свойством ItemsSource
элемента управления, который наследуется от класса ListBase (типично: ListView
или GridView
), создав DataTemplate для отображения каждого элемента списка, как в этом примере:
<Page
xmlns:vm="using:SampleApp.ViewModelsPath"
<Grid>
<ListView ItemsSource="{x:Bind ViewModel.SampleListOfObjectViewModel, Mode=OneWay}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="vm:SampleObjectViewModel">
<StackPanel>
<TextBlock Text="{x:Bind SampleObjectProperty1, Mode=OneWay}"/>
<TextBlock Text="{x:Bind SampleObjectProperty2, Mode=OneWay}"/>
<Button Click="{x:Bind SampleObjectFunction}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
... и все отображаемые данные будут обновляться в реальном времени всякий раз, когда вы их измените!
Надеюсь, все это поможет вам расширить свои знания о том, как готовить WPF / UWP logi c layer , потому что все это работает примерно одинаково даже для приложений WPF (то есть старых настольных программ).
С уважением