Два представления одной и той же ViewModel в пользовательском элементе управления - PullRequest
2 голосов
/ 04 декабря 2010

У меня есть пользовательский контроль многократного использования с моделью представления позади него.Я пытаюсь переключаться между разными представлениями одних и тех же данных.В настоящее время пытаюсь использовать свойство Mode на виртуальной машине для достижения этой цели.

Я создал DataTemplateSelector следующим образом:

<UserControl x:Class="MyUserControl">
    <UserControl.Resources>
        <DataTemplate x:Key="ColumnTemplate">
            <StackPanel>
                <Label Text="{Binding Name}"></Label>
                <Label Text="{Binding Address}"></Label>
                <Label Text="{Binding Occupation}"></Label>
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="AvatarTemplate">
            <StackPanel>
                <Image Source="{Binding ProfilePicture}"></Image>
                <Label Text="{Binding Name}"></Label>
            </StackPanel>
        </DataTemplate>
    <local:DisplayTemplateSelector ColumnTemplate="{StaticResource ColumnTemplate}" AvatarTemplate="{StaticResource AvatarTemplate}" x:Key="displayTemplateSelector" />
</UserControl.Resources>
<Grid>
    <ContentControl Name="cpDisplay" Content="{Binding}" ContentTemplateSelector="{StaticResource displayTemplateSelector}" />
</Grid>
</UserControl>

С классом:

class DisplayTemplateSelector : DataTemplateSelector
{

    public DataTemplate ColumnTemplate {get;set;}

    public DataTemplate AvatarTemplate {get;set;}

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        MainViewModel vm = (MainViewModel)item;

        switch (vm.Mode)
        {
            case MainViewModel.DisplayMode.Column:
                return ColumnTemplate;
            case MainViewModel.DisplayMode.Avatar:
                return AvatarTemplate;
            default:
                return AvatarTemplate;
        }
    }

}

Этот пользовательский контроль находится в MyWindow:

<Grid>
    <controls:MyUserControl x:Name="MyUserControl" DataContext="{Binding}" Margin="0"/>
</Grid>

Который создается с моей моделью представления:

MyWindow w = new MyWindow(_vm);
w.Show();

У меня проблема в том, что item является нулевым во время MainViewModel vm = (MainViewModel)item.Как будто я пытаюсь установить шаблон данных на основе данных, прежде чем данные будут связаны?

Есть ли какой-либо способ выбрать нужный шаблон данных не на основе объекта данных, а как свойство или подобное в пользовательском контроле?

Ответы [ 3 ]

2 голосов
/ 04 декабря 2010

Есть много способов, но вот пара:

<!-- assumes you have a data template selector implementation available as resource MyContentSelector -->
<ContentControl Content="{StaticResource MainViewModel}" ContentTemplateSelector="{StaticResource MyContentSelector}"/>

или:

<!-- assumes you have appropriate boolean properties on your VM -->
<Grid>
    <ContentControl Content="{StaticResource MainViewModel}" ContentTemplate="{StaticResource column}" Visibility="{Binding IsColumnVisible, Converter={StaticResource BooleanToVisibilityConverter}}"/>
    <ContentControl Content="{StaticResource MainViewModel}" ContentTemplate="{StaticResource avatar}" Visibility="{Binding IsAvatarVisible, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</Grid>
0 голосов
/ 05 декабря 2010

Хорошо, наконец-то все заработало, используя свойство в usercontrol и некоторый код:

    public enum DisplayMode
    {
        Column,
        Avatar
    }

    public DisplayMode Mode { get; set; }


    public MyUserControl()
    {
        InitializeComponent();
        Mode = DisplayMode.Avatar;
    }

    private void MyUserControl_Loaded(object sender, RoutedEventArgs e)
    {
        switch (Mode)
        {
            case DisplayMode.Column:
                cpDisplay.ContentTemplate = (DataTemplate)this.Resources["ColumnTemplate"];
                cpDisplay.ApplyTemplate();
                break;
            case DisplayMode.Avatar:
                cpDisplay.ContentTemplate = (DataTemplate)this.Resources["AvatarTemplate"];
                cpDisplay.ApplyTemplate();
                break;
        }
    }

Я удалил код DataTemplateSelector и просто определил шаблоны данных и использовал:

    <ContentPresenter Name="cpDisplay" Content="{Binding}" />
0 голосов
/ 04 декабря 2010

См. DataTemplateSelector Class

DataTemplateSelector

...