• Dynamic


    1、  今天下午在做开发过程中,遇到了一个问题,要往Xml文件中添加新的节点,做个xml开发的都知道该怎么做,这不是什么难事,我卡卡卡卡把这个问题解决了,但是新问题又来了,要对xml中对应的节点数据添加属性更改通知功能???我一听到这个需求就蒙了,我上哪去给xml节点数据整TMD属性更改通知啊。哎。。。。。没办法了,胳膊拧不过大腿啊,只能硬着头皮上咯。

    2、  通过google、bing、百度的搜索,主要让我发现了有个神奇的玩意,那就是ExpandoObject类型,ExpandoObject归属于动态类型,之前只是听说过动态类型,但是一直都只是停留在听说阶段,今天为了解决这个问题终于可以来接近久仰已久的Dynamic了。要学习.net的新东西,肯定是去MSDN找咯,在msdn上看到关于Dynamic的介绍非常齐全,内容非常之多,今天我主要研究的是ExpandoObject。于是我就从最简单的用法开始,自己动手一步步写代码尝试。

    现在开始我第一段代码:

     C#代码:

        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
            {
                dynamic dynObject = new ExpandoObject();
                dynObject.Name = "张益达";
                dynObject.Age = 25;
                dynObject.Time = DateTime.Now;
                this.DataContext = dynObject;
            }
        }

     xaml代码:

    <Window x:Class="WpfApplication2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <StackPanel>
                <Button Width="80" Height="30" Content="按钮1" Click="ButtonBase_OnClick"></Button>
                <TextBlock Text="{Binding Path=Name}"></TextBlock>
                <TextBox Text="{Binding Path=Age, Mode=TwoWay}"></TextBox>
                <TextBlock Text="{Binding Path=Time}"></TextBlock>
            </StackPanel>
        </Grid>
    </Window>

    效果图:

    说明:

    这里就可看出Dynamic的神奇之处了,我没有定义个类型,也没有定义Name、Age、Time这些属性,没错,这就是动态类型的功劳了,它能把我的Name、Age、Time在运行时解析成相应的类型,并且通过前台的数据绑定,把数据显示出来。

     

    第二段代码:

    C#代码:

        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            dynamic dynObject = new ExpandoObject();
    
            private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
            {
               
                dynObject.Name = "张益达";
                dynObject.Age = 25;
                dynObject.Time = DateTime.Now;
                this.DataContext = dynObject;
            }
    
            private void ButtonBase1_OnClick(object sender, RoutedEventArgs e)
            { 
                string newName = dynObject.Name;
                string age = dynObject.Age; 
            }
        }

     xaml代码:

    <Window x:Class="WpfApplication2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <StackPanel>
                <Button Width="80" Height="30" Content="按钮1" Click="ButtonBase_OnClick"></Button>
                <Button Width="80" Height="30" Content="按钮2" Click="ButtonBase1_OnClick"></Button>
                <TextBlock Text="{Binding Path=Name}"></TextBlock>
                <TextBox Text="{Binding Path=Age, Mode=TwoWay}"></TextBox>
                <TextBlock Text="{Binding Path=Time}"></TextBlock>
            </StackPanel>
        </Grid>
    </Window>

    效果图:

     

    说明:

    运行起来先点击 按钮1 然后改变Age的值(从25改成100),再点 按钮2,断点截图中可以看到dynObject.Age的值已经自动变成120,!!!!天啊,这是多么神奇的事啊,值就那么轻易的自己改变了,这不就是要想要的属相自动更改吗?这倒是是真么发生的呢,其实这一切都是ExpandoObject的功劳,不准确的说应该是INotifyPropertyChanged的功劳,为什么这么说呢,在ExpandoObject上按F12看看究竟把:

    有了这幅图就能说明一切了,ExpandoObject是多么强大啊,它既是动态类,又是字典、集合、最最关键的他还有属性更改通知。

     

    第三段代码

    C#代码:

            ObservableCollection<ExpandoObject> source = new ObservableCollection<ExpandoObject>();
            private void ButtonBase3_OnClick(object sender, RoutedEventArgs e)
            {
                for (int i = 0; i < 5; i++)
                {
                    dynamic dynObj = new ExpandoObject();
                    dynObj.Test1 = string.Format("Zhangyida{0}", i);
                    dynObj.Test2 = 25 + i;
                    dynObj.Test3 = DateTime.Now.ToString();
                    dynObj.IsCheck = false;
                    source.Add(dynObj);
                }
                this.DataGrid1.ItemsSource = source;
            }
    
            private void ButtonBase4_OnClick(object sender, RoutedEventArgs e)
            {
                var sourc = source;
                foreach (dynamic item in source)
                {
                    item.IsCheck = false;
                    if (item.Test1 == "Zhangyida1")
                    {
                        item.Test2 = 100;
                    }
                }
            }

    Xaml代码

      <Button Width="80" Height="30" Content="按钮3" Click="ButtonBase3_OnClick"></Button>
                <Button Width="80" Height="30" Content="按钮4" Click="ButtonBase4_OnClick"></Button>
                <DataGrid Name="DataGrid1">
                    <DataGrid.Columns>
                        <DataGridTextColumn Binding="{Binding Path=Test1}"></DataGridTextColumn>
                        <DataGridTextColumn Binding="{Binding Path=Test2}"></DataGridTextColumn>
                        <DataGridTextColumn Binding="{Binding Path=Test3}"></DataGridTextColumn>
                        <DataGridCheckBoxColumn Binding="{Binding Path=IsCheck}"></DataGridCheckBoxColumn>
                    </DataGrid.Columns>
                </DataGrid>

    效果图:

    点击 按钮3:

    点击按钮4:

    说明:

    注意喔,大家看仔细了,看看两幅图的区别,这是通过一个集合来进一步使用了ExpandoObject属性更改通知

    这时候我突然有个一个想法,既然动态类型可以动态的添加属性,那么能不能让我定义的一般实体类也可以有这种功能呢,查看了MSDN发现这个事有搞头,让我的实体类来继承DynamicObject,然后再做并从新实现TrySetMember,大家先看看代码吧

        public class DynamicUser : DynamicObject
        {
            private IDictionary<string, object> dictionary = new ExpandoObject();
    
            public int Count
            {
                get { return dictionary.Count; }
            }
    
            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                string name = binder.Name;
                return dictionary.TryGetValue(name, out result);
            }
    
            public override bool TrySetMember(SetMemberBinder binder, object value)
            {
                dictionary[binder.Name] = value;
                return true;
            }
    
            public int Age { get; set; }
    
            public string Name { get; set; }
    
            public DateTime Time { get; set; }
        }

    这是我的动态实体类,默认有三个字段Age 、Name、Time字段,其实动态添加的属性,我都把它放到了一个Dictionary里面,而且这是个ExpandoObject的字典。

    C#代码:

            dynamic dynUser = new DynamicUser();
            private void ButtonBase5_OnClick(object sender, RoutedEventArgs e)
            {
                dynUser.Age = 10;
                dynUser.Name = "张伟";
                dynUser.Time = DateTime.Now;
                dynUser.ABC = "ddddd";
                var ok = dynUser;
    
                this.DataContext = dynUser;
            }
    
            private void ButtonBase6_OnClick(object sender, RoutedEventArgs e)
            {
                var user = dynUser;
            }

    Xaml代码:

        <Button Width="80" Height="30" Content="按钮5" Click="ButtonBase5_OnClick"></Button>
        <Button Width="80" Height="30" Content="按钮6" Click="ButtonBase6_OnClick"></Button>

    效果图

    说明:大家可以从上图中看到dynUser已经有了ABC了,而且ABC的用法和属性的用法一模一样。

    源代码下载  http://files.cnblogs.com/zwzw/source.rar

  • 相关阅读:
    Unity Find 使用规则
    Unity UGUI
    Unity UGUI
    Unity UGUI
    Unity UGUI
    机器学习:支持向量机识别手写英文字母 SMO算法实现二元分类器
    机器学习:朴素贝叶斯分类器实现二分类(伯努利型) 代码+项目实战
    机器学习:基于CART算法的决策树——分类树与回归树
    机器学习:决策树——分类树 ID3算法 代码+案例
    JAVA
  • 原文地址:https://www.cnblogs.com/zwzw/p/Carl.html
Copyright © 2020-2023  润新知