Win10开发:数据绑定

数据绑定并不是Win10的新东西,早在WP7/Win8时代就有了。但是在Win10有新的特性与改变,这在文章的后面讲解。

下面通过几个简单实例说明几种常用的绑定用法。

1、ElementName的使用:

目标:通过Slider的Value值控制Rectangle的Width属性值

实现:

<Slider x:Name="slider" Minimum="0" Maximum="500" StepFrequency="1"/>
<Rectangle Width="{Binding Value, ElementName=slider}" Height="10" Fill="Blue"/>

目标:通过Slider的Value值控制TextBox的Text属性值

实现:

<Slider x:Name="slider" Minimum="0" Maximum="500" StepFrequency="1"/>
<TextBox Text="{Binding Value, ElementName=slider}" />

2、绑定方式 Mode

上面的例子中通过滑动Slider可以控制TextBox的Text属性,但是却不能改变TextBox的Text值改变Slider的位置。

这时候需要改变Mode的值:

<TextBox Text="{Binding Value, ElementName=slider, Mode=TwoWay}" />

此时当TextBox失去焦点时,Slider的值将跟着变化

Mode的取值可以是OneTime、OneWay和TwoWay,如果不写的话默认值是OneWay

OneTime :仅当应用程序启动时或 DataContext 进行更改时更新目标属性

OneWay:源更新时,目标也更新

TwoWay:源更新时目标也更新,或者目标更新时同时更新源


3、Converter和ConverterParameter

前提:能获取到的是值是某个String值

目标:需要显示一个新的String值的,新的String值是通过修改原始String值得到的

实现:

XAML:

<TextBox x:Name="textBox" Text="apple is good!"/>
<TextBlock Text="{Binding ElementName=textBox, Path=Text,Converter={StaticResource  String2NewStringConverter},ConverterParameter=cherish}"/>


其中ConverterParameter是可选的,就是传递给转换器的参数值

String2NewStringConverter是一个资源,在页面中定义:

 <Page.Resources>
        <local:StringToNewStringConverter x:Key="String2NewStringConverter" />
</Page.Resources>

StringToNewStringConverter是一个实现了IValueConverter接口的类,一般习惯将类名命名为"***Converter":

IValueConverter接口要求实现两个函数,Convert和ConvertBack

StringToNewStringConverter的实现:

public class StringToNewStringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return string.Format("hello windows 10:\nOld String:{0}\nNew String:{1}\nby {2}",value,value.ToString().Replace("apple","microsoft"),parameter);
        }


        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            return value;
        }
    }

效果图:




4、INotifyPropertyChanged和INotifyCollectionChanged

通过下面的示例可以简单实现集合类数据的绑定。

XAML:

 <ListView x:Name="listView" Grid.Row="0">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <SymbolIcon Symbol="{Binding Symbol}"/>
                        <TextBlock Text="{Binding Label}" Margin="24,0,0,0" VerticalAlignment="Center"/>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
</ListView>

C#:

public sealed partial class MainPage : Page
    {
        private List<NavLink> navLinks = new List<NavLink>()
        {
            new NavLink() { Label = "People", Symbol =  Symbol.People  },
            new NavLink() { Label = "Globe", Symbol = Symbol.Globe },
            new NavLink() { Label = "Message", Symbol = Symbol.Message },
            new NavLink() { Label = "Mail", Symbol = Symbol.Mail },
            new NavLink() { Label = "CellPhone", Symbol = Symbol.CellPhone },
        };
        public MainPage()
        {
            this.InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            listView.ItemsSource = navLinks;
            base.OnNavigatedTo(e);
        }
    }

    public class NavLink
    {
        public string Label { get; set; }
        public Symbol Symbol { get; set; }
    }

效果图:



先在有一个需求:通过一个删除按钮实现对页面元素的删除

 <Button Content="删除" Grid.Row="1" VerticalAlignment="Bottom" Width="100" Click="Delete_Click"/>


private void Delete_Click(object sender, RoutedEventArgs e)
{
      navLinks.RemoveAt(0);
}

增加上面的代码后,点击Button发现页面并没有任何改变。那是因为navLinks是一个List集合,没有实现 INotifyCollectionChanged, INotifyPropertyChanged的接口

解决方案:

将List换成ObservableCollection。因为ObservableCollection实现上面的接口,可以简单的理解为ObservableCollection是实现了 INotifyCollectionChanged, INotifyPropertyChanged接口的List。

结论:

如果工程中自定义的类想要实现属性的改变能让UI界面获得通知,只要实现INotifyPropertyChanged接口即可,自定义的集合类需要实现INotifyCollectionChanged接口。


下面是华丽的分割线:

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

接下来的内容是Win10的新特性x:Bind

简单说,x:Bind是x:Binding一定程度上的替代品,据说是80%-90%的情况都可以替代。原来的x:Binding是运行时绑定,而x:Bind是编译时绑定。微软官方的意思就是x:Bind效率高,速度快,方便调试。两个字:好用!


1、x:Bind最重要的一个特点就是强类型

使用x:Binding时是不用考虑数据类型的,错了编译器也不会告诉你。没错有时候App莫名其妙的闪退就是它的锅!(其实是你的锅23333)

当使用x:Bind时,如果类型不匹配编译时,就会出错。


2、x:Bind默认的DataContext就是Code-Behind

所以无需我们设置上下文:"The data context of x:Bind is the code-behind class"

XAML:

 <TextBlock Text="{x:Bind Text}"/>

C#:

 public string Text { get; set; } = "cherish";



3、x:DataType

在使用x:Bind+DataTemplate时,必须指定x:DataType,否则编译不成功



一个简单的实例:

XAML:

 <ContentControl ContentTemplate="{StaticResource MyDataTemplate}"  Content="{x:Bind ViewModel}" />

其中MyDataTemplate是一个模板:

    <Page.Resources>
        <DataTemplate x:Key="MyDataTemplate"
                      x:DataType="local:MainViewModel">
            <StackPanel Orientation="Horizontal">
                <SymbolIcon Symbol="{x:Bind Symbol}"/>
                <TextBlock Text="{x:Bind Label}" Margin="24,0,0,0" VerticalAlignment="Center"/>
            </StackPanel>
        </DataTemplate>
    </Page.Resources>


C#:
  public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }
        public MainViewModel ViewModel { get; set; } = new MainViewModel();
    }

    public class MainViewModel
    {
        public string Label { get; set; } = "People";

        public Symbol Symbol { get; set; } = Symbol.People;
    }


4、x:Bind默认Mode为OneTime

当绑定的数据项在后台代码中发生改变时,必须调用Bindings.Update()方法进行对UI数据的更新。


5、x:Bind绑定事件

XAML:

<Button x:Name="button" Click="{x:Bind Button_Click}"/>

C#:

 public void Button_Click()
 {
    button.Content = "ButtonClick";
 }

6、Bindings.StopTracking() 用于中断绑定


7、x:Bing与ElementName

x:Bing与ElementName不能共存,下面用x:Bind实现1中的“通过Slider的Value值控制Rectangle的Width属性值”

XAML:

<Slider x:Name="slider" Minimum="0" Maximum="500" StepFrequency="1"/>
<Rectangle Width="{x:Bind slider.Value,Mode=OneWay}" Height="10" Fill="Blue"/>
 

看出来了吗,这里必须指明Mode=OneWay,因为默认的Mode=OneTime

当然也可以给Slider控件添加ValueChanged事件来实现:

private void slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
       Bindings.Update();
}

没错,看起来似乎变麻烦了。 但是性能得到了提升,这种小例子是看不出什么区别的。性能与便捷性通常是不能兼得的。


8、绑定与MVVM

待续...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值