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);
            }
        }
    }
}

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>

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>

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>

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>

时间: 2024-08-30 12:10:24

WPF中模板选择和DataContext的一些使用的相关文章

WPF中 ItemsSource 和DataContext不同点

此段为原文翻译而来,原文地址 WPF 中 数据绑定 ItemSource和 DataContext的不同点: 1.DataContext 一般是一个非集合性质的对象,而ItemSource 更期望数据源是 集合对象. 2.DataContext 是 FrameworkElement 类中定义的一个依赖属性(Dependency property),ItemsSource是 在ItemsControl 类中定义的.所有继承自FrameworkElement 的类(控件)都可以使用DataConte

WPF 中动态改变控件模板

在某些项目中,可能需要动态的改变控件的模板,例如软件中可以选择不同的主题,在不同的主题下软件界面.控件的样式都会有所不同,这时即可通过改变控件模板的方式实现期望的功能. 基本方法是当用户点击切换主题按钮是加载新的资源字典,并使用新加载的资源字典替代当前的资源字典这时要用到ResourceManager. 假设现有两个不同的资源字典文件Dictionary1.xaml和Dictionary2.xaml存在于Themes文件夹内: 在MainPage中使用其中一个资源字典作为默认样式文件: <Win

在WPF中使用文件夹选择对话框

开发中有时会想实现"选择某个文件夹"的效果: 在WPF中,使用Microsoft.Win32.OpenFileDialog只能选择文件,FolderBrowserDialog只能用树型的方式选择文件夹,很不好用. 终于找到一个办法,使用Windows API Code Pack 在VS里打开Package Manager Console后输入Install-Package WindowsAPICodePack-Shell获取包后 就可以像这样打开选择文件夹Dialog了: var di

在WPF中获取DataGridTemplateColumn模板定义的内容控件

xaml格式描述: <DataGrid Name="dataGrid" Grid.Row="1" ItemsSource="{Binding}"  >            <DataGrid.Columns>              <DataGridTemplateColumn Header="描述">                    <DataGridTemplateCo

关于WPF中关于样式和模板的区别

百度了下,改天整理. WPF中关于样式和模板的区别: 回答一: 1.WPF样式类似于Web应用程序中的CSS,在WPF中可以为控件定义统一的样式(Style).样式属于资源的一种,例如为Button定义统一的背景颜色和字体: <Window.Resources> <Style  TargetType="Button"> <Setter Property="Background" Value="Yellow" />

wpf 获取datagrid中模板中控件

//获取name为datagrid中第三列第一行模板的控件 FrameworkElement item = dataGrid.Columns[3].GetCellContent(dataGrid.Items[0]); DataGridTemplateColumn temp = dataGrid.Columns[3] as DataGridTemplateColumn; //img是模板的name object c= temp.CellTemplate.FindName("img", i

WPF中的数据模板(DataTemplate)(转)

原文地址 http://www.cnblogs.com/zhouyinhui/archive/2007/03/30/694388.html WPF中的数据模板(DataTemplate)                                                                                                                          周银辉 在WPF中我们可以为自己的数据定制显示方式,也就是说虽然某数据

关于WPF中TextBox行的选择与显示的问题

声明:本文是本人在51CTO上的一篇博文,今天打算将其转载到博客园,以方便自己查阅.原文地址为:http://kestrelsaga.blog.51cto.com/3015222/1542584 最近做了一个小工具,其中用到了WPF中的TextBox控件.对于这个控件的使用,其中主要的一个功能是需要选择指定的行,并将其显示在控件可见区域的视图中(如果不在可视区域时,需要控件自动滚动到改行).在我使用时,发现一个问题,如果当我先将指定的行滚动至视图中,然后在将其选中,则经常会不稳定,有时能定位并选

WPF中的ControlTemplate(控件模板)(转)

原文地址 http://www.cnblogs.com/zhouyinhui/archive/2007/03/28/690993.html WPF中的ControlTemplate(控件模板)                                                                                                                        周银辉 WPF包含数据模板和控件模板,其中控件模板又包括Contro