zoukankan      html  css  js  c++  java
  • WPF DataBinding some other details

    1. RelativeSource
          用来指定一个相对的source位置,通常有以下三种方式:

    (1): RelativeSource.Self
           允许把自己当作相对的元素。
    (2): RelativeSource.FindAncestor
           根据指定的类型(AncestorType)和向上寻找的层次(AncestorLevel)向祖先寻找。例如AncestorLevel
    设为1,则把第一次找到的匹配的object作为参照对象,如果为2,则把第二次匹配的object作为参照对象。
    <StackPanel Background="Blue">
       <TextBlock Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType= {x:Type  StackPanel},    AncestorLevel=1}, Path=Background}" />
    </StackPanel>

    (3): RelativeSource.TemplatedParent
          当自己在一个template里面的时候,取被设置了该template的对象作为参照对象。

    <Window>
    <Window.Resources>
       <ControlTemplate x:Key="myButtonTemplate" TargetType="{x:Type Button}">
          <StackPanel Background="{Binding RelativeSource={RelativeSource
    TemplatedParent},Path=Background}"/>
       </ControlTemplate>
    </Window.Resources>
    <Button Template="{StaticResource myButtonTemplate}" Background="Blue"/>
    </Window>

    在这里,设置了ButtonBackground是什么,则template里的StackPanelBackground就是什么了。
    2. TemplateBindingContentPresenter
        Binding提供了更灵活的绑定方式,但是开销较大。TemplateBinding只可以在以下一种场景使用,
    但是很方便:当一个元素在一个template里面的时候,用TemplateBinding将该元素的某一个属性和
    templat的元素的某一个属性绑定,这样被template的元素的这个属性值就会传给这个元素。
    例如下面的例子:

    <Window x:Class="CommonQuestions.Window1
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="CommonQuestions" Height="300 Width="300
         >
            <Window.Resources>
                <ControlTemplate TargetType="{x:Type Button}" x:Key="buttonTemplate">
                    <Border BorderBrush="{TemplateBinding Property=Background}" 
    BorderThickness="3 >
                        <ContentPresenter Margin="10/>
                    </Border>
                </ControlTemplate>
            </Window.Resources>
            <StackPanel Margin="20>
                <Button Template="{StaticResource buttonTemplate}" 
    HorizontalAlignment="Center" Background="SteelBlue">Hello</Button>
            </StackPanel>
        </Window>

    在这里,ButtonBackground"SteelBlue"就会传递给它所应用的ControlTemplate里的Border
    BorderBrush属性了。TemplateBinding是可以和BindingRelativeSource.TemplatedParent转换的,
    作用一样。上面的也可以写成:
    <Border BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent},
    Path=Background}"/>
    注意这里只能是OneWay的传递方式,要实现其它的传递方式,
    就必须用Binding了。另外,TemplateBinding也提供了ConverterConverterParameter,满足在
    不同类型间传递了。
    ContentPresenter
    ContentPresenter是一个用在ContentControltemplate里的元素,ContentPresenter is used to
    specify where the content should go in the ContentControl's template(也就是说用它指定
    应用这个templateControlContent显示在template里的哪个位置)。
    例如上例中所用到的<ContentPresenter Margin="10/>实际上等价于下面的语句:

    <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate=
    "{TemplateBinding ContentTemplate}" ContentTemplateSelector="{TemplateBinding
    ContentTemplateSelector}" Margin="10/>

    因为对于这里的ContentContentTemplate的声明是任何时候都有的情况,所以我们省略
    成了上面的形式。但是这里说明了我们可以显式的另外指定ContentPresenter Content
    如果我们改成:

    <ContentPresenter Content="{TemplateBinding Background}" Margin="10/>

    以前是把"Hello"显示在templateBorder里,现在显示的却是"#FF4682B4,也就是说被
    新设的值覆盖了。

    3. IValueConverter
    ConvertBack里的实现,如果return Binding.DoNothing,例如:
    public object ConvertBack(object value, Type targetType,
    object parameter, System.Globalization.CultureInfo culture)
        {
    if(...)
            return Binding.DoNothing;
    return ....;
        }

    如果return Binding.DoNothing,则In a one-way binding, the data goes from
    Source -> Converter -> Target. If you return Binding.DoNothing in
    the Convert method, the data transfer goes from Source -> Converter
    and stops there, it does not continue to the target. Future changes
    in the Source will still trigger a
    data transfer,也就是说这次数据传递被取消,但是以后的传递如果不出错,还是
    会继续传递的。如果return null,则当null是合法的source值时,会赋给source
    但不合法时会报错。因为在OneWay binding时,ConvertBack是不会执行的,所以这里
    最好是throw一个Exception,如果有错误执行到这里了,程序会报错,我们也容易发现错误了。

    4. ItemsPanelTemplate
    对于ItemsControl,用ItemsPanelTemplate指定它的所有ItemsLayout,例如
    Items水平或竖直排列,对齐方式等等。
    例如下面的例子创建一个所有Items以水平方向排列的ListBox
    <Style TargetType="ListBox">
      <Setter Property="ItemsPanel">
        <Setter.Value>
          <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"
                        VerticalAlignment="Center"
                        HorizontalAlignment="Center"/>
          </ItemsPanelTemplate>
        </Setter.Value>
      </Setter>
    </Style>
    这里用到了ItemsPanel属性。

    下面的方式不设置ItemsPanel属性,而是通过更改ListBoxControlTemplate
    创建了一个带有rounded corners的水平排列的ListBox
    <Style TargetType="ListBox">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="ListBox">
            <Border CornerRadius="5" Background="{TemplateBinding ListBox.Background}">
              <ScrollViewer HorizontalScrollBarVisibility="Auto">
                <StackPanel Orientation="Horizontal"
                           VerticalAlignment="Center"
                           HorizontalAlignment="Center"
                           IsItemsHost="True"/>
              </ScrollViewer>
            </Border>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
    但是这种方式注意的是要设置StackPanelIsItemsHost属性为true
    然而,我们可以在ControlTemplate中使用ItemsPresenter,让它调用
    ItemsPanelTemplatelayout所有的Items
    <Style TargetType="{x:Type ListBox}">
      <Setter Property="ItemsPanel">
        <Setter.Value>
          <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"
                         VerticalAlignment="Center"
                         HorizontalAlignment="Center"/>
          </ItemsPanelTemplate>
        </Setter.Value>
      </Setter>
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type ListBox}">
            <Border CornerRadius="5"
                    Background="{TemplateBinding ListBox.Background}">
              <ScrollViewer HorizontalScrollBarVisibility="Auto">
                <ItemsPresenter/>
              </ScrollViewer>
            </Border>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

    又如下面的例子,
    <!--Define a control template for a HeaderedItemsControl-->
    <Style TargetType="HeaderedItemsControl">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="{x:Type HeaderedItemsControl}">
            <StackPanel>
              <Grid>
                <Rectangle Fill="{TemplateBinding Background}"/>
                <ContentPresenter ContentSource="Header"/>
              </Grid>
              <Grid>
                <Rectangle Stroke="{TemplateBinding BorderBrush}"/>
                <ItemsPresenter Margin="2,0,0,0"/>
              </Grid>
            </StackPanel>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

    <HeaderedItemsControl  xmlns:sys="clr-namespace:System;
                           assembly=mscorlib"
                           Header="My colors"
                           Background="SteelBlue"
                           BorderBrush="DarkSlateBlue">
      <sys:String>Red</sys:String>
      <sys:String>Yellow</sys:String>
      <sys:String>Blue</sys:String>
      <sys:String>Green</sys:String>
    </HeaderedItemsControl>
    注意这里用ContentPresenterContentSource属性指定了将被template
    的元素的Header属性显示在第一个Rectangle内。后面的ItemsPresenter
    属性指定了在这个Rectangle内显示所有Items,并且所有的ItemsMargin
    2000

    5. BindingNotifyOnSourceUpdatedNotifyOnTargetUpdated属性
    例如NotifyOnTargetUpdated就指示是否触发TargetUpdated事件当数据从sourcetarget传递的时候。默认是false,例如:

    <TextBlock Grid.Row="1" Grid.Column="1" Name="RentText"
      Text="{Binding Path=Rent, Mode=OneWay, NotifyOnTargetUpdated=True}"
      TargetUpdated="OnTargetUpdated"/>

    public void OnTargetUpdated(Object sender, DataTransferEventArgs args)
    {
      // Handle event
    }

    NotifyOnSourceUpdated则是相反方向传递的情况。

    6.注意x:Static的用法

    The code entity referenced must be one of the following:

    • constant
    • static property
    • field
    • enumeration value

    例如:

    <Button FontSize="8" Margin="10, 10, 5, 5" Grid.Column="0" Grid.Row="5"

    HorizontalAlignment="Left"

    Height="{x:Static SystemParameters.CaptionHeight}"

    Width="{x:Static SystemParameters.IconGridWidth}">

    SystemParameters

    </Button>

    7. Binding Path的几种特殊写法

    • To bind to an attached property, place parentheses around the attached property. For example, to bind to the attached property DockPanel.Dock, the syntax is Path=(DockPanel.Dock).
    • When the source is a collection view, the current item can be specified with a slash (/). For example, the clause Path=/ sets the binding to the current item in the view. When the source is a collection, this syntax specifies the current item of the default collection view.
    • Property names and slashes can be combined to traverse properties that are collections. For example, Path=/Offices/ManagerName specifies the current item of the source collection, which contains an Offices property that is also a collection. Its current item is an object that contains a ManagerName property.
    • Optionally, a period (.) path can be used to bind to the current source. For example, Text="{Binding}" is equivalent to Text="{Binding Path=.}".
  • 相关阅读:
    android Fragment和FragmentActivity
    android 生成xml文件
    android:在ViewPager中使用Button
    android延迟执行
    android.os.NetworkOnMainThreadException 异常
    导入android工程没有R文件的解决办法
    20个常用的Java程序块
    Java中的==、equals、hasCode方法
    《head first java 》读书笔记
    【写给自己】2014-03-13
  • 原文地址:https://www.cnblogs.com/bear831204/p/1310987.html
Copyright © 2011-2022 走看看