#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. когда вы закончите со своим вопросом, я подробно прокомментирую ответы 😀