0

Реализация MVVM проекта. У меня есть главное окно MainWindow.xaml, код ниже. В нём, как видно есть Frame, принимающий значение переменной в качестве контента. Изначально в окне устанавливается главная страница. По нажатию на кнопку должна срабатывать команда, которая открывает другую страницу. Также должен быть переход данных, в данном случае на главной странице есть поле для ввода города, эта строка должна переходить на вторую страницу для дальнейней работы:

<Grid>
        <Frame
            Grid.ColumnSpan="3"
            Grid.RowSpan="3"
            Content="{Binding CurrentPage}"
            NavigationUIVisibility="Hidden"
            Opacity="{Binding Opacity}"
            />
</Grid>

Соответственно для окна указал контекст данных:

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainViewModel();
        }
    }

MainViewModel:

internal class MainViewModel : PropertyChangedHelper
    {
        private Page MainPage, WeatherInfo;
    private Page currentPage;
    public Page CurrentPage
    {
        get { return currentPage; }
        set
        {
            currentPage = value;
            OnPropertyChanged();
        }
    }

    private double opacity;
    public double Opacity
    {
        get { return opacity; }
        set
        {
            opacity = value;
            OnPropertyChanged();
        }
    }

    /*public ICommand WeatherCityCommand { get; set; }*/
    public ICommand WeatherCityCommand { get; }

    public MainViewModel()
    {
        MainPage = new View.MainPage();
        WeatherInfo = new View.WeatherInfPage();
        WeatherCityCommand = new RelayCommand(OpenWeatherWindow);

        Opacity = 1;
        CurrentPage = MainPage;
    }

    public void OpenWeatherWindow()
    {
        CurrentPage = WeatherInfo;
    }
}

Команда в принципе не срабатывает при нажатии на кнопку, поэтому окно не открывается. Что я делаю не так? MainPage.xaml:

<TextBox
                    materialDesign:TextFieldAssist.HasClearButton="True"
                    FontFamily="Jura"
                    Background="{DynamicResource Secondary}"
                    Foreground="{DynamicResource BackgroundText}"
                    FontWeight="Bold"
                    Height="25"
                    Width="174"
                    Margin="17,15,15,0"
                    FontSize="15"
                    HorizontalContentAlignment="Center"
                    materialDesign:HintAssist.Hint="Ваш город"/>
            &lt;Button FontWeight=&quot;Bold&quot; FontFamily=&quot;Jura&quot; Content=&quot;Узнать погоду&quot; Background=&quot;{DynamicResource Focus}&quot; Foreground=&quot;{DynamicResource BackgroundText}&quot; Margin=&quot;17,24,15,17&quot; FontSize=&quot;15&quot; Cursor=&quot;Hand&quot; Height=&quot;25&quot;
              Width=&quot;174&quot;
              Command=&quot;{Binding WeatherCityCommand}&quot;&gt;
            &lt;/Button&gt;

Сроки горят, был бы благодарен за быстрый и ценный ответ :)

Gonzy
  • 21
  • У вас два существенных нарушения MVVM: 1. DataContext = new MainViewModel(); - у вас View слой отвечает за создание, срок жизни, и др. ViewModel слоя, когда по правилам MVVM эти слои вообще не должны знать ничего про друг друга (подробней). 2. Page - это UI элемент, а UI по правилам MVVM должны быть в ViewModel слое? Нет. И тут мы понимаем, что Frame не для MVVM, хотите правильно, используйте ContentPresenter. – EvgeniyZ Jun 11 '23 at 09:28
  • Теперь ваша основная проблема: Вот смотрим Command="{Binding WeatherCityCommand}", где у вас WeatherCityCommand? В MainViewModel, ок... А DataContext у MainPage какой? Вы его задали? Я этого не вижу. Думаю ошибку поняли?) Устранить это просто, либо укажите DataContext, либо передайте ссылку на MainViewModel, сохраните ее в свойство внутри страницы и привязку используйте как {Binding Свойство.WeatherCityCommand}, но думаю понимаете, что вы UI элементом оперируете в VM слое, нарушая MVVM? – EvgeniyZ Jun 11 '23 at 09:34
  • Я немного переделал, так как перечитал ТЗ. В приложении должно быть 2 окна, вот как раз в MainWindow у меня главное окно, а в WeatherInfWindow - второе. Мне нужно, чтобы при нажати на кнопку в первом окне, в том же открывалось второе, чтобы короче говоря не создавалось второе окно отдельно, вот MainViewModel: – Gonzy Jun 11 '23 at 09:39
  • private UIElement windowContent; public UIElement WindowContent { get { return windowContent; } set { windowContent = value; OnPropertyChanged(); } }
        private string city;
        public string City
        {
            get { return city; }
            set
            {
                city = value;
                OnPropertyChanged();
            }
        }
    
    – Gonzy Jun 11 '23 at 09:40
  • public ICommand OpenSecondWindowCommand { get; }
        public MainViewModel()
        {
            OpenSecondWindowCommand = new RelayCommand(OpenSecondWindow);
        }
    
    – Gonzy Jun 11 '23 at 09:40
  • private void OpenSecondWindow() { /WeatherInfWindow secondWindow = new WeatherInfWindow(City) { DataContext = this }; WindowContent = secondWindow;/
            WeatherInfWindow weatherWindow = new WeatherInfWindow(City) { DataContext = this };
            WindowContent = weatherWindow.Content as UIElement;
            weatherWindow.Show();
    
            Application.Current.MainWindow.Hide();
        }
    
    – Gonzy Jun 11 '23 at 09:41
  • Возможно ерунду пишу, просто тороплюсь очень – Gonzy Jun 11 '23 at 09:41
  • Создать окно по правилам MVVM это еще тот гемор) Помним ведь, что View не должен знать ничего про VM, а VM не должен знать про View, это самое базовое правилом MVVM, ну а окно это что? Правильно, View (UI) слой, а это значит, что мы не можем просто так взять и в VM слое его создать. Тут нужна некая абстракция, некая обертка над окнами, которая будет где-то за пределами всех слоев оперировать окнами, задавать DataContext, открывать их. Вот одна из реализаций, где по VM некий отдельный класс будет создавать окна, в VM у вас только VM будут. – EvgeniyZ Jun 11 '23 at 09:57

0 Answers0