Показываю, как в UserControl можно засунуть кастомный DepencyProperty и прибиндить к нему свою собственную View Model.
К примеру, пусть будет 2 текстблока, один будет использовать DepencyProperty, другой будет пытаться взять что-то из DataContext, то есть из View Model. Получается вот такая разметка:
UserControl1.xaml
<UserControl x:Class="WpfApp2.UserControl1"
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:WpfApp2"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Style TargetType="{x:Type local:UserControl1}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:UserControl1}">
<StackPanel>
<TextBlock Text="{TemplateBinding MyText}"/>
<TextBlock Text="{Binding MyVMText}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
</UserControl>
DepencyProperty живут в код-бихайнде в данном случае есть одна типа string и называется MyText.
UserControl1.xaml.cs
public partial class UserControl1 : UserControl
{
public static readonly DependencyProperty MyTextProperty = DependencyProperty.Register("MyText", typeof(string), typeof(UserControl1));
public UserControl1()
{
InitializeComponent();
}
public string MyText
{
get => (string)GetValue(MyTextProperty);
set => SetValue(MyTextProperty, value);
}
}
Теперь ViewModel для UserControl.
На самом деле, VM ничего не знает про то, где и какое View будет к ней привязываться. VM просто содержит свойства и как-то их меняет, а View уже на свое усмотрение оттуда берет что-нибудь и как-нибудь это отображает. Но я как программист знаю, что мне нужна VM, обеспечивающая работу конкретного UserControl1, и я ее создаю и называю соответствующим образом.
UserControlViewModel.cs
public class UserControlViewModel : NotifyPropertyChanged
{
private string _myVMText;
public string MyVMText
{
get => _myVMText;
set
{
_myVMText = value;
OnPropertyChanged();
}
}
}
Свойство назвал по-другому, не так как DP, но можно и одинаково. Это я сделал чтобы визуально была разница.
Теперь у нас есть вьюмодель окна, где будет жить этот UserControl1, то есть его экземпляр, там то я и создаю эту VM как обычное свойство, реализующее INotifyPropertyChanged. А это все для того, чтобы если захочется переключить UserControl.DataContext, на другую вьюмодель в рантайме, то INPC нам поможет.
MainViewModel.cs
private UserControlViewModel _userControlVM;
public UserControlViewModel UserControlVM
{
get => _userControlVM;
set
{
_userControlVM = value;
OnPropertyChanged();
}
}
// инициализирую что-нибудь в эту VM в конструкторе главной VM
public MainViewModel()
{
UserControlVM = new UserControlViewModel { MyVMText = "Text for UserControl's VM" };
}
А использую это следующим образом.
MainWindow.xaml
<local:UserControl1 Grid.Column="1" MyText="Text fro DepencyProperty" DataContext="{Binding UserControlVM}"/>
Но вы же скажете, что MyText тоже можно прибиндить к чему угодно!, и я отвечу: да, можно. Какой из способов доставки данных в UserControl вам больше нравится, тот и используйте. Можно вообще обойтись без кастомных DepencyProperty и биндиться только в VM, можно наоборот, можно смешать (но не взбалтывать!). Оба способа валидны и прекрасно подходят для MVVM.
UserControl должен получить эти данные и создать экземпляр личной ViewModel'это неверно. – tym32167 Jun 07 '20 at 17:54Правильно ли я понимаю, что получать входные данные UserControl должен в собственном конструкторе в Code Behind?User Control должен получать данные от вьюмодели через DataContext – tym32167 Jun 07 '20 at 17:54Насколько я понимаю, экземпляр ViewModel'и создается в XAMLэто иногда верно только для главной вьюмодели, но в основном неверно. Идея в том, что UI генерируется по ViewModel, а не ViewModel генерируется по UI – tym32167 Jun 07 '20 at 17:56Таким образом, нужно создать извне экземпляр ViewModel'и и отдельно экземпляр View? Как объяснить View, какой именно экземпляр VIewModel'и использовать в качестве DataContext'а?
– s7onoff Jun 07 '20 at 17:56поэтому не могу понять, как здесь реализовать передачу какого-либо параметра в создаваемый экземпляр ViewModel'ичерез UI это не делается никак. – tym32167 Jun 07 '20 at 17:56DepencyProperty, с которымы можно работать, например как сTextBlock.Text. А вьюмодель может с ними взаимодействовать. Так же у юзерконтрола вообще может не быть своей вьюмодели, если это не требуется. Вы же не заводите отдельную VM для каждогоTextBox? В общем, на выходеUserControl- это простоControlсо своими свойствами и особенностями. Внутренняяя логика может быть и в кодбихайнде, если это не работа с данными а логика поведения самого юзерконтрола, в любом случае кодбихайнд - это View и отвечает он за представление информации. – aepot Jun 07 '20 at 17:58отдельную ViewModel для этого UserControl'а, чтобы она хранила определенное количество данных для негоу вас хвост виляет собакой, вьюмодели не хранят данные для конкретных юзерконтролов, они хранят достаточно данных, чтобы могли быть отрисованы, но они не должны знать как они будут отрисованы и кем. – tym32167 Jun 07 '20 at 18:03Дальше - у меня, например, будет 2 или 3 или 5 одинаковых UserControl'ов, у всех одинаковые ViewModel'и, но у всех разные данные и значит у каждого свой экземпляр ViewModel'и.
Я мыслю как-то неверно?
– s7onoff Jun 07 '20 at 18:06