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>
效果圖
說明:大家可以從上圖中看到
新聞熱點
疑難解答