Команда WPF Не выполняется

#c# #wpf

Вопрос:

Мое главное окно в настоящее время отображает представление года в элементе управления содержимым с помощью модели YearViewModel с привязкой к данным. Когда я нажимаю кнопку «Месяц» в представлении «Год», я хочу, чтобы в главном окне вместо этого отображалось представление «Месяц». Модель MainViewModel (модель представления главного окна не показана) извлекает модель представления для отображения из ‘_navigationStorage.CurrentViewModel» , как показано в NavigateMonthCommand.Выполнить(). Но когда я нажимаю кнопку «Месяц», перейдите в команду «Месяц».Функция Execute() никогда не вызывается.

Не работает ли привязка кнопки «Месяц»? В YearView.xaml я должен указывать текст данных по-другому?

Главное окно.xaml

 <Window x:Class="Calandar.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:viewmodels="clr-namespace:Calandar.ViewModels"
    xmlns:views="clr-namespace:Calandar.Views"
    xmlns:local="clr-namespace:Calandar"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
    <Grid Background="LightSlateGray">
    
        <ContentControl Content="{Binding CurrentViewModel}">
            <ContentControl.Resources>
                <DataTemplate DataType="{x:Type viewmodels:YearViewModel}">
                    <views:YearView/>
                </DataTemplate>
                <DataTemplate DataType="{x:Type viewmodels:MonthViewModel}">
                    <views:MonthView/>
                </DataTemplate>
            </ContentControl.Resources>
        </ContentControl>

    </Grid>
</Window>
 

YearView.xaml

 <UserControl x:Class="Calandar.Views.YearView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Calandar.Views"
         xmlns:viewmodels="clr-namespace:Calandar.ViewModels"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
    <Grid Background="White" DataContext="viewmodels:YearViewModel">
        <StackPanel>
            <TextBlock Text="Year" FontSize="55"/>
            <Button Content="Month" Command="{Binding NavigateMonthCommand}"/>
        </StackPanel>
    </Grid>
</UserControl>
 

YearViewModel.cs

 public class YearViewModel : ViewModelBase
{

    public ICommand NavigateMonthCommand { get; }

    public YearViewModel(NavigationStorage navigationStorage)
    {
        NavigateMonthCommand = new NavigateMonthCommand(navigationStorage);
    }

}
 

NavigateMonthCommand.cs

 public class NavigateMonthCommand : CommandBase
{

    private readonly NavigationStorage _navigationStorage;

    public NavigateMonthCommand(NavigationStorage navigationStorage)
    {
        _navigationStorage = navigationStorage;
    }

    public override void Execute(object parameter)
    {
        ;
        _navigationStorage.CurrentViewModel = new MonthViewModel();
    }

}
 

CommandBase.cs

 public abstract class CommandBase : ICommand
{
    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter) => true;

    public abstract void Execute(object parameter);

    public void OnCanExecuteChanged()
    {
        CanExecuteChanged?.Invoke(this, new EventArgs());
    }
}
 

Комментарии:

1. Определяется ли пользователь Commandbase?

2. @JeroenvanLangen я не совсем уверен, что это значит, но я добавил класс в вопрос.

3. Незначительный совет: замените new EventArgs() на EventArgs.Empty , сохраните экземпляр класса.

4. @JeroenvanLangen хорошо, спасибо!

Ответ №1:

Посмотри на это

Без iNotifyPropertyChanged Viewmodel не может получать данные из интерфейса представления. Вы должны правильно подключиться. Вы должны исходить ViewModelBase из INotifyPropertyChanged .

Я думаю, что вы создали свою базовую модель, вы можете создать метод там.

 public event PropertyChangedEventHandler PropertyChanged;         
public void OnPropertyChanged(string PropertyName)         
{             
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
 

вам нужно вызвать его во время выполнения операции набора свойств в указанной вами модели YearViewModel. Образец:

         private string surName;
        public string SurName
        {
            get { return surName; }
            set { surName = value; OnPropertyChanged(nameof(SurName)); }
        }
 

удачи

Комментарии:

1. Спасибо. Я прочитал документацию. Но где бы я мог вызвать OnPropertyChanged()?

2. @oopsHithere Я думаю , что вы создали свой BaseViewModel , вы можете создать метод там. public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string PropertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName)); }

3. Хорошо, но где я должен вызвать этот метод, чтобы модель представления могла получать данные из представления?

4. вам нужно вызвать его во время выполнения операции набора свойств в указанной вами модели представления. Образец: private string surName; public string SurName { get { return surName; } set { surName = value; OnPropertyChanged(nameof(SurName)); } }

5. когда вы закончите со своим вопросом, я подробно прокомментирую ответы 😀