WPF中模板选择和DataContext的一些使用

如图样:

View结构

MainView(MainViewModel)
|---Guide1View(Guide1ViewModel)
|---Guide2View(Guide2ViewModel)
  |---Guide2_1View1(Guide2_1ViewModel)
  |---Guide2_1View2(Guide2_1ViewModel)

ViewModel实例结构

Main(ViewModelViewModel)
|---CurrentViewModel(GuidePageViewModelBase)
|---PageViewModelList(ObservableCollection<GuidePageViewModelBase>)
  |---Guide1(Guide1ViewModel)
  |---Guide2(Guide2ViewModel)
    |---LVM1(LViewModel)
    |---LVM2(LViewModel)

1、通过ContentControl显示选中的视图模型对应的视图:

<ContentControl Content="{Binding CurrentViewModel}">
    <ContentControl.Resources>
        <DataTemplate DataType="{x:Type viewmodel:Guide1ViewModel}">
            <view:Guide1View/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type viewmodel:Guide2ViewModel}">
            <view:Guide2View/>
        </DataTemplate>
    </ContentControl.Resources>
</ContentControl>

2、Guide2_1View作为一个多次使用的控件,对应一个LViewModel,设置自己的DataContext(这里的背景是该视图的使用个数确定的。当然也可以用ListBox代替):

<view:Guide2_1View DataContext="{Binding Path=DataContext.LVM1,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
<view:Guide2_1View DataContext="{Binding Path=DataContext.LVM2,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />

完整代码:

ViewModel:

using GalaSoft.MvvmLight;

namespace WPF_NestedVMAndView.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        public MainViewModel()
        {
            PageViewModelList = new ObservableCollection<GuidePageViewModelBase>()
            {
                new Guide1ViewModel(),
                new Guide2ViewModel(),
            };
            CurrentViewModel = PageViewModelList[1];
        }

        public const string CurrentViewModelPropertyName = "CurrentViewModel";
        private GuidePageViewModelBase _currentViewModel;
        public GuidePageViewModelBase CurrentViewModel
        {
            get
            {
                return _currentViewModel;
            }

            set
            {
                if (_currentViewModel == value)
                    return;

                _currentViewModel = value;
                RaisePropertyChanged(CurrentViewModelPropertyName);
            }
        }

        public const string PageViewModelListPropertyName = "PageViewModelList";
        private ObservableCollection<GuidePageViewModelBase> _pageViewModelList;
        public ObservableCollection<GuidePageViewModelBase> PageViewModelList
        {
            get
            {
                return _pageViewModelList;
            }

            set
            {
                if (_pageViewModelList == value)
                    return;

                _pageViewModelList = value;
                RaisePropertyChanged(PageViewModelListPropertyName);
            }
        }
    }

    public class GuidePageViewModelBase : ViewModelBase
    {
        public GuidePageViewModelBase(string name)
        {
            Name = name;
        }

        public const string NamePropertyName = "Name";
        private string _name;
        public string Name
        {
            get
            {
                return _name;
            }

            set
            {
                if (_name == value)
                    return;

                _name = value;
                RaisePropertyChanged(NamePropertyName);
            }
        }
    }

    public class Guide1ViewModel : GuidePageViewModelBase
    {
        public Guide1ViewModel()
            : base("Guide1")
        {

        }
    }

    public class Guide2ViewModel : GuidePageViewModelBase
    {
        public Guide2ViewModel() : base("Guide2")
        {
            LVM1 = new LViewModel()
            {
                Text = "LVM1",
            };
            LVM2 = new LViewModel()
            {
                Text = "LVM2",
            };
        }

        public const string LVM1PropertyName = "LVM1";
        private LViewModel _lvm1;
        public LViewModel LVM1
        {
            get
            {
                return _lvm1;
            }

            set
            {
                if (_lvm1 == value)
                    return;

                _lvm1 = value;
                RaisePropertyChanged(LVM1PropertyName);
            }
        }

        public const string LVM2PropertyName = "LVM2";
        private LViewModel _lvm2;
        public LViewModel LVM2
        {
            get
            {
                return _lvm2;
            }

            set
            {
                if (_lvm2 == value)
                    return;

                _lvm2 = value;
                RaisePropertyChanged(LVM2PropertyName);
            }
        }
    }

    public class LViewModel : ViewModelBase
    {
        public const string TextPropertyName = "Text";
        private string _text;
        public string Text
        {
            get
            {
                return _text;
            }

            set
            {
                if (_text == value)
                    return;

                _text = value;
                RaisePropertyChanged(TextPropertyName);
            }
        }
    }
}
View Code

MainView:

<Window x:Class="WPF_NestedVMAndView.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:view="clr-namespace:WPF_NestedVMAndView.View"
        xmlns:viewmodel="clr-namespace:WPF_NestedVMAndView.ViewModel"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{Binding Main,Source={StaticResource Locator}}">
    <DockPanel Margin="20">
        <ListBox ItemsSource="{Binding PageViewModelList}" DisplayMemberPath="Name" SelectedItem="{Binding CurrentViewModel}" DockPanel.Dock="Left" Width="100"/>
        <ContentControl Content="{Binding CurrentViewModel}">
            <ContentControl.Resources>
                <DataTemplate DataType="{x:Type viewmodel:Guide1ViewModel}">
                    <view:Guide1View/>
                </DataTemplate>
                <DataTemplate DataType="{x:Type viewmodel:Guide2ViewModel}">
                    <view:Guide2View/>
                </DataTemplate>
            </ContentControl.Resources>
        </ContentControl>
    </DockPanel>
</Window>
View Code

Guide1View:

<UserControl x:Class="WPF_NestedVMAndView.View.Guide1View"
             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" 
             mc:Ignorable="d" 
             Background="White"
             >
    <Grid>
        <TextBlock Text="{Binding Name}" Margin="10"/>
    </Grid>
</UserControl>
View Code

Guide2View:

<UserControl x:Class="WPF_NestedVMAndView.View.Guide2View"
             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:view="clr-namespace:WPF_NestedVMAndView.View"
             mc:Ignorable="d" 
             Background="White">
    <DockPanel>
        <TextBlock Text="{Binding Name}" Margin="10" DockPanel.Dock="Top"/>
        <view:Guide2_1View DataContext="{Binding Path=DataContext.LVM1,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" DockPanel.Dock="Top"/>
        <view:Guide2_1View DataContext="{Binding Path=DataContext.LVM2,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" DockPanel.Dock="Top"/>
    </DockPanel>
</UserControl>
View Code

Guide2_1View:

<UserControl x:Class="WPF_NestedVMAndView.View.Guide2_1View"
             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" 
             mc:Ignorable="d" 
             Background="White">
    <Grid>
        <TextBlock Text="{Binding Text}" Margin="10"/>
    </Grid>
</UserControl>
View Code

posted @ 2015-04-22 12:10  SubmarineX  阅读(1463)  评论(0编辑  收藏  举报