• WPF 用户控件依赖注入赋值


    前言

    我一直想组件化得去开发WPF,因为我觉得将复杂问题简单化是最好的

    如何组件化开发

    在这里插入图片描述

    主窗口引用

    <Window x:Class="WpfApp1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            xmlns:MD="http://materialdesigninxaml.net/winfx/xaml/themes"
            xmlns:Views="clr-namespace:WpfApp1.Views"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800" >
        <Window.Resources>
            <Style x:Key="my_text" TargetType="TextBlock">
                "FontSize" Value="30" />
                "Margin" Value="8" />
            Style>
        Window.Resources>
        <Window.DataContext >
            
            <local:MainWindowViewModel x:Name="viewModel"/>
        Window.DataContext>
        <Grid>
            
            <Views:ViewA Margin="10"
                    Title="{Binding ElementName=viewModel,Path=TitleValue}" />
        Grid>
    Window>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    cs部分

    namespace WpfApp1
    {
        /// 
        /// Interaction logic for MainWindow.xaml
        /// 
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
        }
    
        public class MainWindowViewModel
        {
            public string TitleValue { get; set; } =  "我是测试数据";
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    控件窗口

        <UserControl.DataContext>
            <local:ViewAViewModel />
        UserControl.DataContext>
    
        <Grid>
            <TextBlock Text="{Binding Title}" />
        Grid>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    /// 
    /// ViewA.xaml 的交互逻辑
    /// 
    public partial class ViewA : UserControl
    {
    
        public static readonly DependencyProperty TitleProperty;
    
        /// 
        /// 为了拿到数据源需要定义一下
        /// 
        private ViewAViewModel ViewModel = new ViewAViewModel();
        public ViewA()
        {
            InitializeComponent();
            ViewModel = (ViewAViewModel)DataContext;
    
        }
        static ViewA()
        {
            //静态构造
            TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(ViewA),new PropertyMetadata("",
                new PropertyChangedCallback((item, res) =>
                {
                    //拿到数据,再次赋值
                    var model =(ViewA)item;
                    model.ViewModel.Title = (string)res.NewValue;
                })));
        }
    
        /// 
        /// 只是为了有代码提示,添加依赖属性后不会被调用
        /// 
    
        public string Title { get; set; }
    
    
    
    
    }
    public partial class ViewAViewModel : ObservableObject
    {
        /// 
        /// 通知更新
        /// 
        [ObservableProperty]
        private string title = "ViewA Title!";
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    依赖注入代码优化

    我将复杂的依赖注入的代码进行了优化,减少了重复内容的输入。

    //原代码
    TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(ViewA), new PropertyMetadata(default,
      new PropertyChangedCallback((item, res) =>
      {
          //拿到数据,再次赋值
          var model = (ViewA)item;
          model.ViewModel.Title = (string)res.NewValue;
      })));
    
    //新代码
    
     TitleProperty = DependencyPropertySet<ViewA, string>("Title", (view, value) =>
     {
         view.ViewModel.Title = value;
     });
    
    
    /// 
    /// 简化依赖注入代码
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    public static DependencyProperty DependencyPropertySet<View,Value>(string name,Action<View,Value> action) 
        where View : class 
    {
        var res=  DependencyProperty.Register(name, typeof(Value), typeof(View), new PropertyMetadata(default,
            new PropertyChangedCallback((item, res) =>
            {
                var model = item as View;
                var value = (Value)res.NewValue;
                if(model != null)
                {
                    action(model, value);
                }else
                   {
                       throw new Exception("model value is null");
                   }
            })));
        return res;
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    更新2023年12月9日

    我现在依赖属性扩展封装在一个静态文件里面

    namespace BlankApp1.Utils
    {
        public class MyWpfExtension<View> where View : class
        {
            
            
            /// 
            /// 简化依赖注入代码
            /// 
            /// 
            /// 
            /// 
            /// 
            /// 
            public DependencyProperty DependencyPropertySet<Value>(string name, Action<View, Value> action)
            {
                var res = DependencyProperty.Register(name, typeof(Value), typeof(View), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                    new PropertyChangedCallback((item, res) =>
                    {
                        var model = item as View;
                        var value = (Value)res.NewValue;
                        if (model != null)
                        {
                            action(model, value);
                        }
                        else
                        {
                            throw new Exception("model value is null");
                        }
                    })));
                return res;
            }
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    简化后的依赖注入

    记得UserControl.xaml里面绑定你ViewModel。这样的话有代码提示

        <UserControl.DataContext>
        	
            <ViewModels:TitileViewModel />
        UserControl.DataContext>
    
    • 1
    • 2
    • 3
    • 4
    namespace BlankApp1.Views
    {
        /// 
        /// TitleView.xaml 的交互逻辑
        /// 
        public partial class TitleView : UserControl
        {
    
            //这个只是为了代码提示,不涉及逻辑。属性类型按照需求更改。
            public MainWindow MainWindow { get; set; }
    
            //初始化依赖属性构造器
            public  static readonly MyWpfExtension<TitleView> MyWpfExtension = new MyWpfExtension<TitleView>();
    
            //这个是简化后的依赖属性
            public static readonly DependencyProperty MainWindowProperty = 
                MyWpfExtension.DependencyPropertySet<MainWindow>("MainWindow", (view, value) =>
            {
                view.TitileViewModel.MainWindow = value;
            });
    
            /// 
            /// DataContext的数据
            /// 
            public TitileViewModel TitileViewModel { get; set; }
    
            public TitleView()
            {
                InitializeComponent();
                //拿到DataContext数据重定向
                TitileViewModel = (TitileViewModel)DataContext;
                TitileViewModel.UserName = "小王";
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    结尾

    我后面要根据Vue的单向数据流,来构思WPF 父子组件如何搭建。其实关键的就是数据流的问题。根据Vue的单向数据流,父组件直接设置子组件的属性,子组件通过回调函数回调变化。我打算写个项目实战一下。

    WPF仿网易云 CSDN 博客专栏

    在这里插入图片描述

  • 相关阅读:
    jmap:java内存映像工具【详细】
    AI服装生成,帮你完成服装设计的最后一步
    【leetcode C++】最小栈
    什么样的vue面试题答案才是面试官满意的
    QT两个类之间使用信号槽
    10 个高质量 AI 助手工具站点,你值得拥有的哦
    Java学习笔记(二)
    Vue语法模板续篇
    【Unity记录】编写一个超实用的单例模式模板
    Azure Data Factory(七)数据集验证之用户托管凭证
  • 原文地址:https://blog.csdn.net/qq_44695769/article/details/133888200