Передайте SelectedItem в ViewModel UserControl внутри DataTemplate - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть этот действительно простой код MVVM, созданный с помощью Prism:

  • 2 Модели (Person, Company - общий интерфейс IContact) с 2 ViewModels (Prism) и 2 Views (UserControl)
  • 1 ViewModel (коллекция интерфейса IContact) с 1 представлением (ListBox, связанный с коллекцией, и ContentControl, связанный с SelectedItem ListBox с DataTemplateSelector, который возвращает один из двух пользовательских элементов управления, основанных на типе SelectedItem)

Как я могу передать объект Model (Person или Company) из SelectedItem (IContact) ListBox в один из двух ViewModel (PersonViewModel или CompanyViewModel), которые соответствуют представлению, возвращаемому DataTemplateSelector (PersonView или CompanyView))?

Спасибо!


Код много, но он действительно прост:

У меня есть следующие классы моделей:

public interface IContact
{
    string Address { get; set; }
}

public class Person : IContact
{
    public string Address { get; set; }
}

public class Company : IContact
{
    public string Address { get; set; }
}

У меня есть эти классы ViewModel:

public class ContactViewModel : Prism.Mvvm.BindableBase
{
    private ObservableCollection<IContact> _contacts = new ObservableCollection<IContact>();
    public ObservableCollection<IContact> Contacts
    {
        get { return _contacts; }
        set { SetProperty(ref _contacts, value); }
    }
}

public class PersonViewModel : Prism.Mvvm.BindableBase
{
    private Person _person; // I want to set this from the ListBox's SelectedItem
    public Person Person
    {
        get { return _person; }
        set { SetProperty(ref _person, value); }
    }
}

public class CompanyViewModel : Prism.Mvvm.BindableBase
{
    private Company _company; // I want to set this from the ListBox's SelectedItem
    public Company Company
    {
        get { return _company; }
        set { SetProperty(ref _company, value); }
    }
}

У меня есть эти классы View:

<UserControl x:Class="ContactView"
             xmlns:prism="http://prismlibrary.com/"
             prism:ViewModelLocator.AutoWireViewModel="True" >
    <UserControl.Resources>
        <DataTemplate x:Key="PersonDataTemplate">
            <local:PersonView>
                // How can I pass the SelectedItem to the ViewModel of this UserControl?
            </local:PersonView>
        </DataTemplate>
        <DataTemplate x:Key="CompanyDataTemplate">
            <local:CompanyView>
                // How can I pass the SelectedItem to the ViewModel of this UserControl?
            </local:CompanyView>
        </DataTemplate>
        <dataTemplateSelectors:contactDataTemplateSelector x:Key="templateSelector"
              PersonDataTemplate="{StaticResource PersonDataTemplate}" 
              CompanyDataTemplate="{StaticResource CompanyDataTemplate}"/>
    </UserControl.Resources>
    <Grid>
        // RowDefinitions here
        <ListBox ItemsSource="{Binding Contacts}" x:Name="myListBox">
            // ItemTemplate here
        </ListBox>
        <ContentControl Grid.Row="1" 
            Content="{Binding ElementName=myListBox, Path=SelectedItem}" 
            ContentTemplateSelector="{StaticResource templateSelector}" />
    </Grid>
</UserControl>

Person:

<UserControl x:Class="PersonView"
             xmlns:prism="http://prismlibrary.com/"
             prism:ViewModelLocator.AutoWireViewModel="True" >
    <Grid>
        <TextBlock Text="{Binding Person.Address}" />
    </Grid>
</UserControl>

Компания:

<UserControl x:Class="CompanyView"
             xmlns:prism="http://prismlibrary.com/"
             prism:ViewModelLocator.AutoWireViewModel="True" >
    <Grid>
        <TextBlock Text="{Binding Company.Address}" />
    </Grid>
</UserControl>

И это:

public class ContactDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate PersonDataTemplate { get; set; }
    public DataTemplate CompanyDataTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item is Person)
        {
            return PersonDataTemplate;
        }
        if (item is Company)
        {
            return CompanyDataTemplate;
        }
    }
}

1 Ответ

0 голосов
/ 27 ноября 2018

Не используйте представление сначала (иначе ViewModelLocator) здесь.Сначала перейдите к модели представления.

Длинная версия:

Make Contacts (источник элемента списка) содержит модели представления.Затем напрямую свяжите SelectedItem с элементом управления контентом.

В списке используется один шаблон данных для отображения контактов, а в элементе управления контентом - другой.Вам даже не нужен селектор, просто установите DataType в своих шаблонах данных.

Когда у вас уже есть элемент, который вы хотите показать (т.е. его модель представления), просто свяжите и покажите, чтоодин.Если вы хотите перейти к экрану в вашем приложении (например, диалоговому окну входа в систему), используйте ViewModelLocator.По сути, это обходной путь для , а не , когда модель представления готова.

...