C# Xamarin 數據綁定入門基礎


C# Xamarin 數據綁定入門基礎

關於數據綁定

Xamarin 單向、雙向綁定

Xaml綁定

C#代碼綁定

在此之前,幾段 偽代碼 幫助像我一樣菜的同學入門。。。

假如說,有兩個控件,一個是滑動條(Slider),一個是顯示文本的標簽(Label)。

            Slider slider = new Slider()
            {
                Maximum = 1,
                Value = 10
            };

            Label label = new Label();
            label.Text = slider.Value.ToString();

滑動條(Slider)滑動的最小單位是 1,初始化值是 10。

我們想用標簽(Label)顯示滑動條的值,在代碼里可以直接賦值。

            label.Text = slider.Value.ToString();

但是,這樣只能獲取一次值,我們想滑動條每次滑動,標簽動態顯示滑動條的值,這時候就需要綁定。

方式1:

            Slider slider = new Slider()
            {
                Maximum = 1,
                Value = 10
            };

            Label label = new Label();
            label.Text = "666"; // 隨便初始化一個值

            label.BindingContext = slider;      // 與一個對象相關聯

            // 設置一個綁定
            // 將 Label 類型的 Text 與 slider 的 Value 屬性綁定起來
            label.SetBinding(Label.TextProperty,"Value");

方式2:

            Slider slider = new Slider()
            {
                Maximum = 1,
                Value = 10
            };

            Label label = new Label();
            label.Text = "666"; // 隨便初始化一個值

            Binding binding = new Binding()
            {
                Source = slider, // 關聯數據源
                Path = "Value"   // 綁定數據源的屬性
            };

            // 綁定
            label.SetBinding(Label.TextProperty, binding);

上面里,有關鍵字需要記住

BindingContext()、SetBinding()、Binding、Source、Path。

視圖-視圖綁定

視圖-視圖綁定,即 UI 控件間的綁定,使用 Xaml 代碼即可完成,不需要 C#代碼。

上一節中,使用 偽代碼 來作為示范,顯示了兩種綁定方式,下面將以兩種方式為例,編寫 Xaml 代碼的綁定。

首先,要建立數據源

<Slider x:Name="slider" Maximum="1.0" VerticalOptions="CenterAndExpand" />

綁定數據使用 {Binding ... ...}

然后按照第一種方式就行綁定

        <Label x:Name="label" 
               BindingContext="{x:Reference Name=slider}"    
               Text="{Binding Path=Value}" />

x:Reference 是拓展標記,在 XAML 標記中其他地方聲明的實例的引用。 指明所引用的元素的 x:Name。就是一種固定格式,主要是里面的 Name,要填寫數據控件的 X:Name 屬性。

{Binding Path=Value} 表明操作是 Binding ,即綁定數據,綁定的數據是 slider 的 Value 屬性。

上面綁定方式,先在 BindingContext 屬性中綁定數據源對象,再在 Text 屬性中綁定 數據源對象 的 Value 屬性。

第二種方式

        <Label Text="{Binding  Source={x:Reference Name=slider}, Path=Value}" />

第二種方式,直接使用 {Binding ... ... } 綁定數據,Source 設置要綁定的數據源對象,Path 綁定了這個對象的某個屬性。

為了讓界面好看一些,總結上面的代碼,寫成

    <StackLayout>
        <Label x:Name="label" 
               BindingContext="{x:Reference Name=slider}"    
               Text="{Binding Path=Value}" />
        
        <Slider x:Name="slider" Maximum="1.0" VerticalOptions="CenterAndExpand" />
        
        <Label Text="{Binding  Source={x:Reference Name=slider}, Path=Value}" />

    </StackLayout>

但是上面的小數點位數太多,不符合我們需要的格式,我們可以使用 StringFormat 對數據進行格式化。

Text="{Binding Path=Value,StringFormat='{0:F1}'}

綁定模式

綁定枚舉

綁定類型的BindingMode枚舉:

  • Default
  • OneWay -值從源傳輸到目標
  • OneWayToSource -值從目標傳輸到源
  • TwoWay -值傳輸源和目標之間的這兩種方式
  • OneTime-數據從源到目標進行,但僅當BindingContext發生更改時

上面的的數據綁定,是一對一的,而且是單向的數據綁定,是先有 Slider 控件,再在 Label 中綁定。

而且實際場景,1對1並且數據雙向影響、1對多並且多個數據源數據匯集到一個控件等。

單個控件的不同屬性都可以綁定數據。 但是,每個控件只能有一個BindingContext,因此,在該視圖上的多個數據綁定必須全部引用同一對象的屬性。

如果你使用上小節的第一種方式的話,那么只能綁定=一個對象和使用這個對象的屬性。

如果使用第二種方法,則可以綁定多個數據源。

一對多-目標綁定源數據

根據之前的示例,假如 Label 的多個屬性,同時要綁定不同的數據,可以這樣寫。

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <!-- Scale:大小, Rotation:旋轉角度 -->
        <Label x:Name="label"
               Text="TEXT"
               Scale="{Binding Source={x:Reference Name=slider1},Path=Value}"   
               Rotation="{Binding Source={x:Reference Name=slider2},Path=Value}"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <!-- 用來控制大小 -->
        <Slider x:Name="slider1"
                Grid.Row="1" Grid.Column="0"
                Value="5"
                Maximum="10" />


        <!--控制旋轉角度 -->
        <Slider x:Name="slider2"
                Grid.Row="2" Grid.Column="0"
                Maximum="360"/>
    </Grid>

一對多-源對象綁定目標

上面的方法不太靈活,假設 Label 是公用的,要在 Label 里面配置多個屬性的數據來源,要通過自身編寫綁定,而且一個屬性只能綁定一個數據對象。

為了降低耦合度,降低 Label 綁定數據的復雜程度,並且使得多個對象都可以修改 Label 的屬性。

我們可以反過來,創建多個控件,Label 是數據源,其他控件是目標源,但是數據卻是從其他控件提供給 Label 的。有的繞,沒事,下面舉例說明。

        <!-- Scale:大小, Rotation:旋轉角度 -->
        <Label x:Name="label"
               Text="TEXT"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <!-- 用來控制大小 -->
        <Slider x:Name="scaleSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="1" Grid.Column="0"
                Maximum="10"
                Value="{Binding Scale, Mode=TwoWay}" />

        <!--控制旋轉角度 -->
        <Slider x:Name="rotationSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="2" Grid.Column="0"
                Maximum="360"
                Value="{Binding Rotation, Mode=OneWayToSource}" />

label 不作任何處理,而 scaleSlider 和 rotationSlider 把 label 作為數據源綁定,從綁定的定義來說, label 是數據源, label 的屬性數據將 作為 目標控件 scaleSlider、 rotationSlider 的屬性值。

咦?好像搞錯了,我們是要通過別的控件,去修改 label 的屬性值,怎么變成了用 label 的屬性值當作 此控件 的屬性值了?

原因在於使用了 Mode 。

OneWayToSource 枚舉:值從目標傳輸到源。

從綁定的代碼和定義來說,label 是數據源,滑動條是目標,但是數據是反向流通的。

文本框雙向綁定

示例代碼如下

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="2*" />
            <RowDefinition Height="2*" />
            <RowDefinition Height="2*" />
            <RowDefinition Height="2*" />
            <RowDefinition Height="2*" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="2*" />
            <ColumnDefinition Width="2*" />
            <ColumnDefinition Width="2*" />
            <ColumnDefinition Width="2*" />
            <ColumnDefinition Width="2*" />
        </Grid.ColumnDefinitions>
        <Editor x:Name="edit1"
                Grid.Row="0"
                Grid.Column="1"
                Grid.ColumnSpan="2"
                Text="a"/>
        
        <Editor x:Name="edit2"
                Grid.Row="1"
                Grid.Column="1"
                Grid.ColumnSpan="2"
                Text="{Binding Source={x:Reference edit1},Path=Text,Mode=TwoWay}"/>
    </Grid>

官方示例

微軟官方文檔有一個示例代碼量比較多,有興趣可以參考一下

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.SliderTransformsPage"
             Padding="5"
             Title="Slider Transforms Page">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <!-- Scaled and rotated Label -->
        <Label x:Name="label"
               Text="TEXT"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <!-- Slider and identifying Label for Scale -->
        <Slider x:Name="scaleSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="1" Grid.Column="0"
                Maximum="10"
                Value="{Binding Scale, Mode=TwoWay}" />

        <Label BindingContext="{x:Reference scaleSlider}"
               Text="{Binding Value, StringFormat='Scale = {0:F1}'}"
               Grid.Row="1" Grid.Column="1"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for Rotation -->
        <Slider x:Name="rotationSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="2" Grid.Column="0"
                Maximum="360"
                Value="{Binding Rotation, Mode=OneWayToSource}" />

        <Label BindingContext="{x:Reference rotationSlider}"
               Text="{Binding Value, StringFormat='Rotation = {0:F0}'}"
               Grid.Row="2" Grid.Column="1"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for RotationX -->
        <Slider x:Name="rotationXSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="3" Grid.Column="0"
                Maximum="360"
                Value="{Binding RotationX, Mode=OneWayToSource}" />

        <Label BindingContext="{x:Reference rotationXSlider}"
               Text="{Binding Value, StringFormat='RotationX = {0:F0}'}"
               Grid.Row="3" Grid.Column="1"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for RotationY -->
        <Slider x:Name="rotationYSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="4" Grid.Column="0"
                Maximum="360"
                Value="{Binding RotationY, Mode=OneWayToSource}" />

        <Label BindingContext="{x:Reference rotationYSlider}"
               Text="{Binding Value, StringFormat='RotationY = {0:F0}'}"
               Grid.Row="4" Grid.Column="1"
               VerticalTextAlignment="Center" />
    </Grid>
</ContentPage>

簡單的集合綁定

MainPage.xaml 里添加

    <ListView x:Name="lview">
    </ListView>

MainPage.xaml.cs 里,改成

    public partial class MainPage : ContentPage
    {
        public static List<string> lists = new List<string> {"a","b","c","d","e","f" };
        public MainPage()
        {
            InitializeComponent();
            lview.ItemsSource = lists;
        }
    }

運行后,會自動出現列表。

關於 ListView ,后面的文章會更詳細地介紹。


免責聲明!

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



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