WPF 使用用户控件UserControl来切换界面(二)

在上一篇文章中https://www.cnblogs.com/lizhiqiang0204/p/12367553.html我们使用按键Button来切换界面的,这次我们使用自定义的ItemsControl数据模板来切换页面。MainWindow.xaml如下

<Window.DataContext>
        <local:MainWindowVeiwModel></local:MainWindowVeiwModel>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Border Grid.Column ="0"  BorderThickness="3" BorderBrush="Gray" >
            <ScrollViewer Grid.Row="2">
                <ItemsControl ItemsSource="{Binding Items}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Grid Style="{StaticResource MenuItemGrid}"> 
                                <Border MouseDown="UIElement_OnMouseDown" Style="{StaticResource MenuItem}"   Background="{Binding BackColor}"   >
                                    <TextBlock Grid.Row="0" Grid.Column="1" Style="{StaticResource H5}"  Text="{Binding Title}"/>
                                </Border>
                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </ScrollViewer>
        </Border>

        <Border Grid.Column ="1" BorderBrush="Gray" BorderThickness="3" >
            <ContentPresenter  Content="{Binding Content}"/>
            <!--使用内容呈现器来显示用户控件界面-->
        </Border>
    </Grid>
MainWindow.xaml

MainWindow.xaml.cs如下

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            var sample = (SampleVm)((Border)sender).DataContext;//Border属于ItemsControl的其中一员,所以(Border)sender).DataContext 是MainWindowVeiwModel类成员Items数组中的其中一类(即SampleVm)
            var hvm = (MainWindowVeiwModel)DataContext;//MainWindow的数据上下文指定MainWindowVeiwModel类
            hvm.Content = (UserControl)Activator.CreateInstance(sample.Content);//主页面MainWindow.xaml中的内容呈现器ContentPresenter指向选中Items数组中的UserControl句柄。
            hvm.Items[hvm.SelectId].BackColor = new SolidColorBrush(Colors.Transparent);//把上一次选中的背景色改成透明色
            hvm.Items[sample.Id].BackColor = new SolidColorBrush(Colors.Gray);//把这次选中的背景色改成灰色
            hvm.SelectId = sample.Id;//已选择的ID改成本次选中的ID

        }
    }
MainWindow.xaml.cs

MainWindow的DataContext上下文类MainWindowViewModel类如下

public class MainWindowVeiwModel : INotifyPropertyChanged
    {
        private UserControl _content;
        private SampleVm[] _Items;
        public int SelectId;

        public MainWindowVeiwModel()//在构造方法中向Items注册各个用户控件、id以及对应的标题
        {
            _Items = new[]
            {
                new SampleVm("页面1", typeof(UserControl1),0),
                new SampleVm("页面2", typeof(UserControl2),1),
            };
        }
        //ItemsControl中的数据模板绑定SampleVm类数组
        public SampleVm[] Items
        {
            get { return _Items; }
            set
            {
                _Items = value;
                OnPropertyChanged("Items");
            }
        }
        //主页面的内容呈现器
        public UserControl Content
        {
            get { return _content; }
            set
            {
                _content = value;
                OnPropertyChanged("Content");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
MainWindowVeiwModel

保存各个页面信息的类SampleVm如下

public class SampleVm : INotifyPropertyChanged
    {
        private SolidColorBrush _BackColor;
        public SampleVm(string title, Type content, int id)
        {
            Title = title;
            Content = content;
            Id = id;
        }
        public int Id { get; private set; }
        public string Title { get; set; }
        public Type Content { get; set; }

        public SolidColorBrush BackColor 
        {
            get { return _BackColor; }
            set { _BackColor = value; OnPropertyChanged("BackColor"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
SampleVm

App资源字典如下

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:UserControl_change_interface4">
    <Style x:Key="Title" TargetType="TextBlock">
        <Setter Property="HorizontalAlignment" Value="Center"></Setter>
        <Setter Property="Foreground" Value="#303030"></Setter>
        <Setter Property="TextAlignment" Value="Center"></Setter>
        <Setter Property="TextWrapping" Value="Wrap"></Setter>
    </Style>


    <Style x:Key="H3" TargetType="TextBlock" BasedOn="{StaticResource Title}">
        <Setter Property="FontSize" Value="24"></Setter>
    </Style>
    <Style x:Key="H5" TargetType="TextBlock" >
        <Setter Property="FontSize" Value="20"></Setter>
    </Style>

    <Style x:Key="H6" TargetType="Label" >
        <Setter Property="Foreground" Value="Blue"></Setter>
        <Setter Property="FontSize" Value="30"></Setter>
    </Style>

    <Style x:Key="MenuItem" TargetType="Border">
        <!--<Setter Property="Cursor" Value="Hand"></Setter>-->
        <Setter Property="Height" Value="50"></Setter>
        <Setter Property="BorderThickness" Value="0 1 0 1"></Setter>
        <Setter Property="BorderBrush" Value="#EBEBEB"></Setter>
        <!--<Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="WhiteSmoke"></Setter>
            </Trigger>
        </Style.Triggers>-->
    </Style>

    <Style x:Key="MenuItemGrid" TargetType="Grid">
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="WhiteSmoke"></Setter>
            </Trigger>
        </Style.Triggers>
    </Style>
</ResourceDictionary>
AppDictionary.xaml

源码下载地址 https://github.com/lizhiqiang0204/UserControl-change-interface2_1

整体效果如下

MainWindowVeiwModel类中是直接引用UserControl1和UserControl2的,如果想在MainWindow.xaml.cs中访问修改UserControl1实体类类里面的成员,那只能访问在实体类成员前加static修饰,前面的例程中用户控件成员确实使用static修饰的。当然也可以在MainWindowVeiwModel类中实例化用户控件类,每次切换页面直接更改把主页面的内容呈现器ContentPresenter的Content指向MainWindowVeiwModel中实例化的成员就可以改变页面。该例程所有前台.xaml不变,所有后台.cs文件均有改变。

public partial class MainWindow : Window
    {
        public MainWindowVeiwModel MW; 
        public MainWindow()
        {
            InitializeComponent();
            MW = (MainWindowVeiwModel)DataContext;//MW就是MainWindowVeiwModel实体类
        }

        private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            var sample = (SampleVm)((Border)sender).DataContext;//Border属于ItemsControl的其中一员,所以(Border)sender).DataContext 是MainWindowVeiwModel类成员Items数组中的其中一类(即SampleVm)
            MW.Content = MW.Items[sample.Id].User;//主页面MainWindow.xaml中的内容呈现器ContentPresenter指向选中Items数组中的UserControl句柄。
            MW.Items[MW.SelectId].BackColor = new SolidColorBrush(Colors.Transparent);//把上一次选中的背景色改成透明色
            MW.Items[sample.Id].BackColor = new SolidColorBrush(Colors.Gray);//把这次选中的背景色改成灰色
            MW.SelectId = sample.Id;//已选择的ID改成本次选中的ID

        }

        private void btnClearCountClick(object sender, RoutedEventArgs e)
        {
            (MW.User1 as UserControl1).myStr = "0";
            (MW.User1 as UserControl1).i = 0;
            (MW.User2 as UserControl2).myStr = "0";
            (MW.User2 as UserControl2).i = 0;
        }
    }
MainWindow.xaml.cs
public class MainWindowVeiwModel : INotifyPropertyChanged
    {
        private UserControl _content;
        public SampleVm[] _Items;
        public int SelectId;
        public UserControl User1 = new UserControl1();
        public UserControl User2 = new UserControl2();

        public MainWindowVeiwModel()//在构造方法中向Items注册各个用户控件、id以及对应的标题
        {
            _Items = new[]
            {
                new SampleVm("页面1", User1,0),
                new SampleVm("页面2", User2,1),
            };
        }
        //ItemsControl中的数据模板绑定SampleVm类数组
        public SampleVm[] Items
        {
            get { return _Items; }
            set
            {
                _Items = value;
                OnPropertyChanged("Items");
            }
        }
        //主页面的内容呈现器
        public UserControl Content
        {
            get { return _content; }
            set
            {
                _content = value;
                OnPropertyChanged("Content");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
MainWindowVeiwModel.cs
public class SampleVm : INotifyPropertyChanged
    {
        private SolidColorBrush _BackColor;
        public SampleVm(string title, Type content, int id)
        {
            Title = title;
            Content = content;
            Id = id;
        }
        public SampleVm(string title, UserControl user, int id)
        {
            Title = title;
            User = user;
            Id = id;
        }
        public int Id { get; private set; }
        public string Title { get; set; }
        public Type Content { get; set; }
        public UserControl User { get; set; }

        public SolidColorBrush BackColor 
        {
            get { return _BackColor; }
            set { _BackColor = value; OnPropertyChanged("BackColor"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
SampleVm.cs
public partial class UserControl1 : UserControl, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public  int i = 0;

        private  string _myStr = "0";
        public  string myStr //Label 标签内容绑定到这个myStr字符串
        {
            get { return _myStr; }
            set
            {
                _myStr = value;
                OnPropertyChanged("myStr");//异步更新属性
            }
        }
        public UserControl1()
        {
            InitializeComponent();
            DataContext = this;//设置绑定数据的上下文为UserControl1类
        }

        //累加按键处理事件
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            i++;//按一下数值累加一次
            myStr = i.ToString();//把累加完后的数值转换成字符串赋给标签内容值(立刻更新标签内容)
        }

    }
UserControl1.xaml.cs
public partial class UserControl2 : UserControl, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public  int i = 0;
        private string _myStr = "0";
        public  string myStr //Label 标签内容绑定到这个myStr字符串
        {
            get { return _myStr; }
            set
            {
                _myStr = value;
                OnPropertyChanged("myStr");//异步更新属性
            }
        }

        public UserControl2()
        {
            InitializeComponent();
            DataContext = this;//设置绑定数据的上下文为UserControl2类
        }
        //累加按键处理事件
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            i++;//按一下数值累加一次
            myStr = i.ToString();//把累加完后的数值转换成字符串赋给标签内容值(立刻更新标签内容)
        }
    }
UserControl2.xaml.cs

源码下载地址https://github.com/lizhiqiang0204/UserControl-change-interface2_2 

效果图如下

原文地址:https://www.cnblogs.com/lizhiqiang0204/p/12617924.html