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


接着上一篇來侃。

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

  這兒不知道用實體這個詞恰不恰當,湊活着理解就行了。他可以是一個類實例,也可以是一個集合。

  所以,相應的我們就引入兩個Demo,第一個介紹用簡單的類作為作為數據源,第二個就介紹用一個集合作為數據源

  廢話不多說,來看demo,我先上代碼,后上分析

 

  DEMO1:

  XAML頁面

    <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#代碼:

  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 = "不明"; } } }

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

  在執行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,正是這兩個接口提供了這種通知機制!

 

至此。我的心得就完了。。但總感覺講的不夠,不清楚。以后把其中的小技巧在發篇博文談談。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM