[uwp開發]數據綁定那些事(2)

接着上一篇來侃。html

二.實體到控件之間的綁定c#

  這兒不知道用實體這個詞恰不恰當,湊活着理解就好了。他能夠是一個類實例,也能夠是一個集合。函數

  因此,相應的咱們就引入兩個Demo,第一個介紹用簡單的類做爲做爲數據源,第二個就介紹用一個集合做爲數據源post

  廢話很少說,來看demo,我先上代碼,後上分析this

 

  DEMO1:url

  XAML頁面spa

    <Page.Resources>
        <local:User x:Key="user"></local:User>
    </Page.Resources>
    <Grid>
        <StackPanel DataContext="{StaticResource user}" HorizontalAlignment="Center">
            <TextBlock x:Name="tbID" Text="{Binding Path=ID}"></TextBlock>
            <TextBlock x:Name="tbName" Text="{Binding Path=Name}"></TextBlock >
            <TextBlock x:Name="tbGender" Text="{Binding Path=Gender}"></TextBlock>
        </StackPanel>
    </Grid>

  

User類:調試

  public class User
    {
        public int ID{get;set}
        public string Name{get;set}
        public string Gender{get;set;}
    }

 

C#代碼:code

  public sealed partial class MyPage : Page
    {
        public MyPage()
        {
            this.InitializeComponent();
User user
=Resources["user"] as User; if (user != null) { user.ID = 10000; user.Name = "CQ"; user.Gender = "不明"; } } }

  上面兩坨就是所有代碼了,在這兒我說一下執行大概流程。htm

  在執行MyPage類的構造函數時,咱們經過User user=Resources["user"] as User拿到定義在MyPage頁面中的靜態資源User類的實例,而後對其賦值,運行程序後,咱們發現控件上顯示出來了

  咱們賦值的數據。

  其實,咱們在xaml中定義了三個TextBlock控件用來顯示User類中的三個屬性,可是咱們只在他們的binding中只聲明瞭Path,並無指定ElementName,也就是數據源,這時候他們會查找他們的父級

  元素的數據源,這個數據源必須含有ID,User,Gender三個屬性。而在他們的父級元素StackPanel中定義了屬性DataContext(數據上下文),它在這兒指明瞭數據源,是誰呢?就是「user」,它定義在靜態

  資源中。而後在MyPage類的構造函數中,拿到了類User的實例,爲他賦值後,最後經過數據綁定的技術,他們最終顯示在屏幕上!注意:當他們顯示後,若是人爲修改了user類中的屬性值,這種改變是

      不會在界面上顯示出來的。若是想讓它跟着變該怎麼辦?往下看!

 

  在Demo1中的代碼實際是沒有啥實際用途的,想要有用途的,咱們把它改造一下!!!

 

  以前說了,咱們須要在User類實例的屬性值發生改變後,讓改變後的數據也顯示在界面上。因此作以下改動!只須要改動User類就能夠了!

  

  public class User : INotifyPropertyChanged
    {
        private int _id;
        private string _name;
        private string _gender;
        public int ID
        {
            get
            {
                return _id;
            }

            set
            {
                _id = value;
                OnPropertyChanged();
            }
        }

        public string Name
        {
            get
            {
                return _name;
            }

            set
            {
                _name = value;
                OnPropertyChanged();
            }
        }

        public string Gender
        {
            get
            {
                return _gender;
            }

            set
            {
                _gender = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName]string propertyName="")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

  其實理解仍是比較簡單。試想,提供一種機制,在user屬性改變後,就通知系統說「個人值變了,你丫趕忙給我再界面上表達出來」,那麼這個機制就經過讓User繼承INotifyPropertyChanged這個

  接口來實現。

  對比這個類和以前的,除了實現了接口INotifyPropertyChanged接口外,還定義了一個公共方法OnPropertyChanged,其次全部的屬性的set方法里加了OnPropertyChanged()方法,用來通知

  屬性值發生了改變。

  提示小技巧:CallerMemberName特性的做用是在調用OnPropertyChanged方法時,把屬性的名稱做爲參數傳進入,若是不加的話,在調用時就須要手動輸入屬性名稱,這樣出錯的概率就比較大!

  置於INotifyPropertyChanged的真正內部原理,請msdn!...實際上是我不太懂!

  好了,作了如上一番修改後,就是先咱們須要的功能了!

 

     DEMO2

  此次咱們玩個有用的,吧一個集合中的數據綁定到一個列表中!

  先上代碼!!!

  xaml:

    <StackPanel>
            <Button Content="改變" Click="Button_Click"></Button>
            <ItemsControl x:Name="itemsControl" ItemsSource="{Binding}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding ID,Mode=OneWay}"/>
                            <TextBlock Text="{Binding Name,Mode=OneWay}" ></TextBlock>
                        </StackPanel>
                    </DataTemplate>
                   
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </StackPanel>

  product:

  public class Product
    {
        private int _id;
        private string _name;
        public int ID
        {
            get { return _id; }
            set
            {
                _id = value;
             }
        }
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
            }
        }
    }

  c#:

  

  public sealed partial class MyPage : Page
    {
        List<Product> list = null;
        public MyPage()
        {
            this.InitializeComponent();


            list = new List<Product>
            {
                new Product { ID=1,Name="土豆" },
                new Product{ ID=2,Name="馬鈴薯"},
                new Product{ ID=3,Name="洋芋"}
               
            };
            
            itemsControl.ItemsSource = list;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (list != null)
            {
                list.Add(new Product { ID = 4, Name = "Potato" });
            }
        }
    }

  

  這是運行結果。先不要在乎那個「改變」按鈕。

  此次定義了一個ItemsControl列表控件,而且對其ItemTemplate 定義了一個模板,知識仍是數據綁定。不懂能夠看個人這篇文章DataTemplate和ControlTemplate聯繫與區別

  而後定義了一個泛型集合List<Product>,添加了三條數據後,把它設置爲ItemsControl的數據源,注意這兒不用DataContext設置,用ItemSource屬性!(而這區別能夠百度!)

  以後運行程序,發現數據已經成功顯示在界面上了。

 

  到這兒,已經實現瞭如何把一個集合中的數據顯示在一個列表控件中!

  而的「改變」按鈕的做用是想List中添加一條數據,但在點擊後,界面上並無反應,可是經過調試發現,數據的確添加到了List中,知識沒有顯示出來而已,結合咱們以前一篇博文,

  應該能猜到,這兒缺乏某種通知機制。當咱們把List<Product>換爲ObservableCollection<Product>後,會發現可以改變數據了。

  經過查看定義發現ObservableCollection<T>實現了接口INotifyCollectionChanged, INotifyPropertyChanged,正是這兩個接口提供了這種通知機制!

 

至此。個人心得就完了。。但總感受講的不夠,不清楚。之後把其中的小技巧在發篇博文談談。

相關文章
相關標籤/搜索