Во время освоения паттерна столкнулся с несколькими проблемами, которые опишу в данном вопросе. В своей программе из сторонних библиотек использую только Caliburn.Micro.
Вот код программы:
1) MainView.xaml
<Window x:Class="WpfMvvmTest5.Views.MainView"
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:local="clr-namespace:WpfMvvmTest5.Views"
mc:Ignorable="d"
Title="MainView"
Height="450"
Width="800">
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<ListBox Grid.Row="1" Grid.Column="1" x:Name="ItemsListBox" SelectedItem="0" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding TextBlockText}" x:Name="TextBlock1"/>
<ContentControl Grid.Row="3" Grid.Column="1" Content="{Binding ElementName=ItemsListBox, Path=SelectedItem.Content}" />
</Grid>
2) MainViewModel.cs
using Caliburn.Micro;
using System.Collections.Generic;
using System.Windows;
using WpfMvvmTest5.Models;
using WpfMvvmTest5.Views;
namespace WpfMvvmTest5.ViewModels
{
public class MainViewModel : Conductor<object>
{
private string _name;
public string Name
{
get => _name;
set
{
_name = value;
NotifyOfPropertyChange(() => Name);
}
}
private string _textBlockText;
public string TextBlockText
{
get => _textBlockText;
set
{
_textBlockText = value;
NotifyOfPropertyChange(() => TextBlockText);
}
}
public MainViewModel()
{
_textBlockText = "Test";
Items.Add(new ItemsModel("Useless", null));
Items.Add(new ItemsModel("TextChangerView", new TextChangerView()));
Items.Add(new ItemsModel("TextChangerViewModel", new TextChangerViewModel()));
}
private List<ItemsModel> _items = new List<ItemsModel>();
public List<ItemsModel> Items
{
get => _items;
set => _items = value;
}
public void ChangeTextButton()
{
TextBlockText = "Text changed! Wow!";
MessageBox.Show("This is MainVM!"); //TextChangerViewModel.ChangeTextButton();
}
}
}
3) ItemsModel.cs
namespace WpfMvvmTest5.Models
{
public class ItemsModel
{
public string Name { get; set; }
public object Content { get; set; }
public ItemsModel(string name, object content)
{
Name = name;
Content = content;
}
}
}
4) TextChanger.xaml
<UserControl x:Class="WpfMvvmTest5.Views.TextChangerView"
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:cal="http://www.caliburnproject.org"
xmlns:local="clr-namespace:WpfMvvmTest5.Views"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Content="Change da text" cal:Message.Attach="ChangeTextButton"/>
</Grid>
5) TextChangerViewModel.cs
using System.Windows;
namespace WpfMvvmTest5.ViewModels
{
public class TextChangerViewModel
{
public static void ChangeTextButton() => MessageBox.Show("This is TextChangerVM!");
}
}
6) Структура решения
В данный момент программа запускает ContentControl TextChangerView после выбора в ListBox соответствующего итема. Вопросы, собственно, следующие:
1) В UserControl'е содержится только кнопка, по клику на которую должно выводиться сообщение о том, что вызов метода произошел в TextChangerViewModel. На деле же вызывается аналогичный метод из родительского (в котором был создан UserControl) View. Если же попробовать в ListBox'е выбрать TextChangerViewModel, то в ContentControl'e не происходит вызов нужного UserControl. В этом и заключается первый вопрос - как в данном случае обратиться в ViewModel, а не View, чтобы впоследствии при нажатии на кнопку в данном ContentControl вызывалась функция из TextChangerViewModel?
2) В случае, если по клику на кнопку вызывается функция ChangeTextButton из TextChangerViewModel, возможно ли изменить текст TextBlock'а, находящегося в MainView? Если конкретнее, меня интересует ситуация, когда TextBlock - это заголовок, и он меняется при смене итема в ListBox. И вообще, стоит ли делать такое, или это какое-то грубое нарушение принципов MVVM?
3) Возможно ли обращаться к TextBlock из кода модели, и правильно ли это для использования MVVM? В своей программе на WinForms, когда у меня менялся этап выполнения задачи, я выделял жирным шрифтом текущий этап выполнения задачи, вопрос в том, как это сделать на WPF с использованием данного паттерна.
Виртуальный выделенный сервер (VDS) становится отличным выбором
В Laravel, через $text = DB::table('articles')->select('text')->get(); получил переменную с результатом ` Object (
Не могу понять как работают валидаторы в YII, вот мне приходит пост запрос в контроллер: