2014-02-17 2 views
3

Я довольно новичок в 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 

ответ

2

Я вижу несколько вопросов:

  1. Вы набор ChildUserControl.DataContext в XAML, но экземпляры ChildUserControl уже получают контекст данных от связывания в ContentPresenter. Вы можете безопасно удалить его.

  2. ContentPresenter может содержать только один ребенок контроль. Когда вы создаете новую модель представления и устанавливаете ее на CurrentView, старая модель просмотра забыта, старый ChildUserControl удален, затем создается новый ChildUserControl, который представляет новую модель представления.

Как вы путешествуете по тому, как он выглядит? Я не вижу соответствующего кода.

+0

Удаление «ChildUserControl.DataContext» в XAML сделало трюк! Вы бог! Я не понимал, что у дочерних представлений был установлен их контекст данных при привязке к 'ContentPresenter'. Я действительно не могу вас поблагодарить! –

+0

Если один элемент управления содержит другой, дочерний элемент управления (почти) всегда наследует контекст данных от родительского элемента управления, независимо от того, как он был добавлен (презентаторы, шаблоны, неявно и т. Д.). Если родительский элемент управления является списком ('ItemsControl'), дочерние элементы управления будут привязаны к отдельным элементам из' ItemsSource'. – Athari

+0

Это на самом деле делает вещи намного проще. Плюс я получал ошибки времени разработки в своих DataContexts моих дочерних элементов управления пользователя. Вы только что сговорились с моим клиентом, что я боюсь LOL. Еще раз спасибо! –

Смежные вопросы