Я новичок как в WPF, так и в MVVM, и при попытке установить DataContext на один и тот же экземпляр моей ViewModel в двух разных представлениях возникла проблема.
Это произошло потому, что:
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
создаст новый экземпляр модели представления для каждого представления.
Чтобы обойти это, я решил создать класс, в котором хранятся статические экземпляры каждой модели ViewModel, которую я использовал. Затем в файле cs каждого представления я бы установил для DataContext соответствующую ViewModel из этого статического класса.
Это работает, но не кажется лучшей идеей для больших программ, где могут потребоваться несколько экземпляров ViewModel одновременно.
Каковы лучшие подходы к этой проблеме? Существуют ли разумные способы иметь несколько представлений с использованием одного и того же экземпляра ViewModel?
Или это плохая практика - следует ли мне разрабатывать программу с одним представлением для каждой модели представления?
Caliburn.Micro предлагает несколько представлений для одной модели представления через свойство "cal: View.Context". Может быть, вы можете посмотреть в их исходном коде, как это технически достигается.
@LadislavOndris Итак, я создал простую игру в крестики-нолики, ViewModel содержит экземпляр класса Game, содержащий всю информацию, необходимую для игры, и у меня есть два отдельных представления: одно для игрового поля (сетка кнопок 3x3) и один для информации об игре (чей ход, количество побед и т. д.)





Вы можете создать экземпляр этой модели представления в App.xaml, чтобы она была доступна для всего приложения.
<Application.Resources>
<local:ViewModel x:Key = "sharedViewModel" />
</Application.Resources>
Затем в ваших представлениях, когда вы хотите использовать этот текст данных, вы делаете следующее ...
DataContext = "{StaticResource sharedViewModel}"
Простой и легкий, а также один из рекомендуемых подходов - это реализация ViewModelLocator.
Идея определила все модели ViewModel в классе ViewModelLocator и получила доступ к ViewModel везде, где это необходимо. Использование одной и той же модели представления в другом представлении не будет проблемой.
public class ViewModelLocator
{
private MainWindowViewModel mainWindowViewModel;
public MainWindowViewModel MainWindowViewModel
{
get
{
if (mainWindowViewModel == null)
mainWindowViewModel = new MainWindowViewModel();
return mainWindowViewModel;
}
}
private DataFactoryViewModel dataFactoryViewModel;
public DataFactoryViewModel DataFactoryViewModel
{
get
{
if (dataFactoryViewModel == null)
dataFactoryViewModel = new DataFactoryViewModel();
return dataFactoryViewModel;
}
}
}
App.xaml
xmlns:core = "clr-namespace:MyViewModelLocatorNamespace"
<Application.Resources>
<core:ViewModelLocator x:Key = "ViewModelLocator" />
</Application.Resources>
Применение
<Window ...
DataContext = "{Binding Path=MainWindowViewModel, Source = {StaticResource ViewModelLocator}}">
см .: коды Итак, вопрос скопированы оттуда .. так как я не могу скопировать коды из моего проекта ..
Каковы на самом деле две возможности возврата свойства MainViewModel?
@Alfie, извини, я не совсем понимаю твой вопрос. Я говорил, что вместо того, чтобы определять каждую ViewModels как ресурсы в App.Xaml, вы можете определить их в классе и использовать класс в привязках. это также рекомендуемый подход. см. обновленный код ..
Этот ответ настолько недооценен, но настолько прост и эффективен, спасибо
У меня был тот же вопрос, и я не мог найти хорошего ответа. Поразмыслив над этим некоторое время, я пришел к выводу, что в большинстве случаев лучше всего создать сопоставление «один к одному» между моделью представления и представлением. Поэтому в этой ситуации я бы создал две отдельные модели представления, которые наследуются от базовой модели представления. Таким образом, вы можете поместить все, что является общим в базовой модели представления, и добавить любые поля или методы, которые могут отличаться от более конкретной модели представления. Если модели представления действительно эквивалентны, вы можете спросить себя, почему у вас вообще два отдельных представления. Вы можете объединить их в одно представление. Возможно, вам нужно иметь два отдельных представления, но это просто необходимо учитывать.
Я использую структуру призмы, а также искал решение использовать одну модель представления для многих (дочерних) представлений. В призме есть два возможных решения:
Согласно документу призмы, мое решение выглядит так.
В загрузчике призмы:
Container.RegisterTypeForNavigation<MyView>("MyView");
В модели просмотра:
private void DisplayView(string viewName)
{
RegionManager.Regions["ContentRegion"].Context = this; // set viewmodel
RegionManager.RequestNavigate("ContentRegion", viewName);
}
В коде каждого представления:
public MyView()
{
InitializeComponent();
ObservableObject<object> viewRegionContext = RegionContext.GetObservableContext(this);
viewRegionContext.PropertyChanged += this.ViewRegionContext_OnPropertyChangedEvent;
}
private void ViewRegionContext_OnPropertyChangedEvent(object sender, PropertyChangedEventArgs args)
{
if (args.PropertyName == "Value")
{
var context = (ObservableObject<object>)sender;
DataContext = context.Value; // get viewmodel as DataContext
}
}
У меня нет для тебя ответа. Я никогда не сталкивался с описанной вами ситуацией, когда несколько представлений назначали бы одну модель представления. Не могли бы вы сказать, что пытаетесь сделать? Мне просто интересно.