Я довольно новичок в WPF и шаблоне MVVM, поэтому, пожалуйста, со мной. Я работаю над проектом для клиента и решил использовать преимущества WPF с точки зрения привязки данных и декларативного подхода к дизайну пользовательского интерфейса. Но у меня есть огромная проблема, понимающая связь между моими представлениями и ViewModels.Убедитесь, что каждый дочерний элемент UserControl создает собственный экземпляр ViewModel
У меня есть UserControl (ParentUserControl) и дочерний UserControl (ChildUserControl). Внутри этого ParentUserControl у меня есть ContentPresenter, который может содержать несколько экземпляров ChildUserControl. У ChildUserControl есть несколько списков со списком и текстовые поля, отображающие информацию из моей модели. Пользователь может открыть как можно больше ChildUserControls в ParentUserControl, нажав кнопку «Добавить новую». В моем ParentViewModel я храню экземпляры каждого ChildViewModel, созданного с пользователем, добавляет новый элемент ChildUserControl в ParentUserControl. Пользователь может перемещаться по элементам ChildUserControls с помощью кнопок «Просмотреть Next» и «View Previous».
Все это отлично работает, за исключением случаев, когда пользователь делает выбор или изменяет текст любого элемента управления в любом ChildUserControl, это изменение распространяется по всем элементам ChildUserControls, которые пользователь создал или использовал один ViewModel для всех представлений. Я пробовал все, что я могу придумать, с использованием и без использования набора инструментов MVVM Light (похоже, это спасет меня в кучу времени в будущем).
Мой вопрос в том, как я могу быть абсолютно уверен, что каждый раз, когда создается новый вид, он получает свой экземпляр своего ViewModel? Я застрял на этом в течение нескольких дней !!! Благодаря!
'ПРИМЕЧАНИЕ: Этот код не является фактическим продуктом. Это просто продемонстрировать проблему, с которой я сталкиваюсь с реальным приложением. Не бойтесь отвечать на C#, если это необходимо, мой предпочтительный язык в любом случае. О, и я пытаюсь завершить этот проект с помощью Pure MVVM. Спасибо!!!
Код:
ParentUserControl:
<UserControl x:Class="ParentUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MVVM_Light_Test_Application"
Height="350" Width="525">
<UserControl.Resources>
<DataTemplate DataType="{x:Type local:ChildUserControlViewModel}">
<local:ChildUserControl/>
</DataTemplate>
</UserControl.Resources>
<UserControl.DataContext>
<local:MainViewModel/>
</UserControl.DataContext>
<Grid>
<StackPanel Width="auto" Height="200">
<ContentPresenter Content="{Binding CurrentView}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
</ContentPresenter>
</StackPanel>
<StackPanel>
<Button Command="{Binding ChangeUserControlCommand}" Content="Click To Change View"/>
</StackPanel>
</Grid>
</UserControl>
ChildUserControl:
<UserControl x:Class="ChildUserControl"
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:MVVM_Light_Test_Application"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Background="{Binding BGColor, UpdateSourceTrigger=PropertyChanged}">
<UserControl.DataContext>
<local:ChildUserControlViewModel/>
</UserControl.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="149*"/>
<ColumnDefinition Width="151*"/>
</Grid.ColumnDefinitions>
<StackPanel Height="200" Width="auto">
<StackPanel>
<ComboBox x:Name="cboExampleObjects" Margin="5" ItemsSource="{Binding Customers}" DisplayMemberPath="Details" SelectedItem="{Binding SelectedCustomer}"/>
</StackPanel>
<StackPanel Grid.Column="1">
<TextBox x:Name="txtObjectPropertyValue" Text="{Binding SelectedCustomer.Name}" Margin="5"/>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
Родитель вид Модель:
Public Class MainViewModel
Inherits ViewModelBase
Public Sub New()
_currentView = New ChildUserControlViewModel
ChangeUserControlCommand = New RelayCommand(AddressOf ChangeUserControl)
End Sub
Private _currentView As ViewModelBase
Public Property CurrentView As ViewModelBase
Get
Return _currentView
End Get
Set(value As ViewModelBase)
_currentView = value
RaisePropertyChanged("CurrentView")
End Set
End Property
Public Property ChangeUserControlCommand As RelayCommand
Public Sub ChangeUserControl()
CurrentView = New ChildUserControlViewModel
CType(CurrentView, ChildUserControlViewModel).BGColor = Nothing
End Sub
End Class
Детский вид Модель:
Импорт System.Collections.ObjectModel
Public Class ChildUserControlViewModel
Inherits ViewModelBase
Public Sub New()
_customes = New ObservableCollection(Of Customer)(New List(Of Customer)({New Customer With {.Name = "TestName1", .CustomerNumber = 1}, New Customer With {.Name = "TestName2", .CustomerNumber = 2}}))
End Sub
Private _customers As ObservableCollection(Of Customer)
Public Property Customers As ObservableCollection(Of Customer)
Get
Return _customers
End Get
Set(value As ObservableCollection(Of Customer))
_customers = value
RaisePropertyChanged("Customers")
End Set
End Property
Private _selectedCustomer As Customer
Public Property SelectedCustomer As Customer
Get
Return _selectedCustomer
End Get
Set(value As Customer)
If _selectedCustomer Is Nothing OrElse String.Compare(value.Name, _selectedCustomer.Name) <> 0 Then
_selectedCustomer = value
RaisePropertyChanged("SelectedCustomer")
End If
End Set
End Property
Private _bgColor As SolidColorBrush
Public Property BGColor As SolidColorBrush
Get
Dim random As New Random
Return New SolidColorBrush(Color.FromArgb(50, Random.Next(0, 255), Random.Next(0, 255), Random.Next(0, 255)))
End Get
Set(value As SolidColorBrush)
Dim random As New Random
_bgColor = New SolidColorBrush(Color.FromArgb(50, random.Next(0, 255), random.Next(0, 255), random.Next(0, 255)))
RaisePropertyChanged("BGColor")
End Set
End Property
End Class
Удаление «ChildUserControl.DataContext» в XAML сделало трюк! Вы бог! Я не понимал, что у дочерних представлений был установлен их контекст данных при привязке к 'ContentPresenter'. Я действительно не могу вас поблагодарить! –
Если один элемент управления содержит другой, дочерний элемент управления (почти) всегда наследует контекст данных от родительского элемента управления, независимо от того, как он был добавлен (презентаторы, шаблоны, неявно и т. Д.). Если родительский элемент управления является списком ('ItemsControl'), дочерние элементы управления будут привязаны к отдельным элементам из' ItemsSource'. – Athari
Это на самом деле делает вещи намного проще. Плюс я получал ошибки времени разработки в своих DataContexts моих дочерних элементов управления пользователя. Вы только что сговорились с моим клиентом, что я боюсь LOL. Еще раз спасибо! –